在C语言中如果已经知道了一个数据的内存地址,怎样直接从内存中读取出该数据?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C语言中如果已经知道了一个数据的内存地址,怎样直接从内存中读取出该数据?相关的知识,希望对你有一定的参考价值。

我刚学C语言,用的是DEV-C++软件。最近刚学到指针。我定义了一个指针变量,然后通过取地址符&取得了我已经定义的一个int数据的内存地址。但是我不想通过指针变量来直接输出该int数据的值,而是想直接读取内存的数据,看看和我定义的int数据值是否相同。
例程:
#include<stdio.h>
int main()

int a=123,b=1234567;
int *m,*n;
m=&a;
n=&b;
//printf("*m=%d\t,*n=%d\n",*m,*n); //这里不用指针变量直接输出int数据
printf("m=%d\t,n=%d\n",m,n);
return 0;

通过这个程序,我知道了m , n的值。它们是int a,b的内存地址,但是不知道怎样直接读取这2个地址的内存数据,看看是否和我定义的值相同。

要读取内存数据的话,只能通过指针,你只能通过自己定义一个int的指针,让他指向一个内存地址,然后通过*指针的形式读出来。
你说的“我不想通过指针变量来直接输出该int数据的值,而是想直接读取内存的数据,看看和我定义的int数据值是否相同。”是没意义的,就好像你要确定我这个人是不是我这个人一样,如果你一定要写的话,可以写成这样。
#include<stdio.h>
int main()

int a=123,b=1234567;
int adda=&a,addb=&b;
int *m,*n;
m=adda;
n=addb;
//printf("*m=%d\t,*n=%d\n",*m,*n); //这里不用指针变量直接输出int数据
printf("m=%d\t,n=%d\n",a,b);
return 0;

这里的m和n已经和a,b没有任何逻辑联系了,他们只是表示两个内存段的数据而已。
再明确点可以写成
#include<stdio.h>
int main()

int a=123,b=1234567;
int adda=&a,addb=&b;//adda和addb仅仅表示两个内存地址
int contenta,contentb;
contenta=*adda;
contentb=*addb;//这两句的含义是两个内存地址里面的内容,他们和变量a,b没有逻辑关系
//printf("*m=%d\t,*n=%d\n",contenta,contentb); //这里不用指针变量直接输出int数据
printf("m=%d\t,n=%d\n",a,b);
return 0;

这里就是你说的比较a以及a所在的内存块(adda)里面内容是不是和a相等
参考技术A #include <stdio.h>
#include <string.h>

void main()

int *p;
int i=10;

p=(int*)0x0012ff78;//i的地址
printf("%d\n",*p);


输出的结果为10,你先调试下,可以知道i的地址
*P等价于*(int*)0x0012ff78本回答被提问者采纳
参考技术B #include<stdio.h>
int main()

int a=123,b=1234567;
int *m,*n;
m=&a;
n=&b;
printf("*m=%d\t,*n=%d\n",*m,*n);//打印指针指向的值
printf("m=%d\t,n=%d\n",m,n);//打印指针内存地址对应的十进制数,因为过大,会显示为一个 负数
printf("m=%p\t,n=%p\n",m,n);//打印指针类型的数据,即指针本身的地址
getch();
return 0;


输出的结果是:

*m=123 ,*n=-10617
m=-54 ,n=-52
m=FFCA ,n=FFCC

可以看到,b的值已经不是1234567,因为定义的b是个2个字节的,最大是65536,再大的数就会溢出,然后显示为负数的,同理,FFCA,FFCC也是过大,所以,m,n对应的十进制也是负数。追问

我这里没有出错:
*m=123 , *n=1234567
m=2293620 ,n=2293616
int 好像占4个字节

追答

对了,不同的平台可能int的字节大小也不一定的,与平台有关,平时开发,用的是size_t类型的。

参考技术C 调试,vc6 有调试功能,就是加一个断点,再点击调试图标,不是感叹号,调到你想看的那句后,工作空间下边有两个窗口,右边的那个有左右两排网格,在左边输入你的变量或地址,右边会自动显示对应的值,大致就是这样,如果有错的话,你自己试试 参考技术D *和&是一对相反意义的运算符,一个取值(仅连地址量),一个取地址(仅连变量)。

怎样获取串口地址

我是个新手
我要编一个在vxworks从串口收发数据的程序
但不知道怎么从串口读写
请大侠们帮忙
谢了
vxworks中这样做也可以吗
串口的地址我怎么知道

如果是在操作系统中,你是不需要知道串口地址的。直接用设备名打开就可以。系统内的设备名可以用devs查看,一般是/tyCo/0和/tyCo/1

如果是在bootrom中,可以用BSP提供的函数,一般在sysSerial.c中,sysChanGet(i)。设置中断或查询方式后然后输出
参考技术A 用API函数实现串行通讯

以往的DOS系统是通过DOS中断和BIOS中断向用户提供串行接口的通讯能力。在Windows环境下,C++的开发工具既没有提供象DOS和BIOS中那样专门的串行通讯控制方法,也不允许用户直接控制串口的中断。

为了保证资源共享,Windows系统完全接管了各种硬件资源,使用中断来控制端口将破坏系统的多任务性,使系统的稳定性受到影响。但Windows同时也提供了功能强大的API函数使用户能间接的控制串行通讯。

1、实现串行通讯的相关API函数

API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。常用函数及作用如表5-1所示。

表5-1 常用串行通讯API函数及其作用

函数名 作用
CreateFile 打开串口
GetCommState 检测串口设置
SetCommState 设置串口
BuilderCommDCB 用字符串中的值来填充设备控制块
GetCommTimeouts 检测通信超时设置
SetCommTimeouts 设置通信超时参数
SetCommMask 设定被监控事件
WaitCommEvent 等待被监控事件发生
WaitForMultipleObjects 等待多个被监测对象的结果
WriteFile 发送数据
ReadFile 接收数据
GetOverlappedResult 返回最后重叠(异步)操作结果
PurgeComm 清空串口缓冲区,退出所有相关操作
ClearCommError 更新串口状态结构体,并清除所有串口硬件错误
CloseHandle 关闭串行口

2、打开串口

函数CreateFile原本用于打开文件,但它同样可用于打开一个通信端口。与系统中其他对象一样,通信端口也是用句柄来标识的。CreateFile函数返回被操作的通信端口句柄,其调用方法如下:

HANDLE CreateFile (

LPCTSTR lpFileName, //指向文件名字符串的指针

DWORD dwDesireAccess, //操作模式

DWORD dwShareMode, //共享方式

LPSECURITY_ATTRIBUTES lpSecurityAttributes,

//指向安全属性的指针

DWORD dwCreationDistribution,//文件建立方式

DWORD dwFlagsAndAttributes //文件属性

HANDLE hTemplateFile) //模板文件句柄

lpFileName:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字。当用CreateFile打开串口时,这个参数可用“COM1”指定串口1,用“COM2”指定串口2,依此类推。

dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或ENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值。用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;

dwShareMode:指定此文件可以怎样被共享。因为串行口不支持任何共享模式,所以dwShareMode必须设为0;

lpSecurityAttributes定义安全属性,一般不用,可设为NULL。Win 9x下该参数被忽略;

dwCreationDistribution定义文件创建方式, 对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;

dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;

hTemplateFile 指向一个模板文件的句柄,串口无模板可言,设为NULL。在 Windows 9x下该参数必须为NULL。

用异步读写方式打开串口1的函数调用如下:

m_hComm = CreateFile(“COM1”, //打开串口1

GENERIC_READ | GENERIC_WRITE,//读写方式

0, //不能共享

NULL, //不用安全结构

OPEN_EXISTING, //打开已存在的设备

FILE_FLAG_OVERLAPPED, //异步方式

0); //无模板

串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_VALUE(0XFFFFFFFF)。

3、串口设置

第一次打开串口时,串口设置为系统默认值,函数GetCommState和SetCommState可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。程序中可先用GetCommState检索端口的当前设置,修改其中的部分字段后再用SetCommState进行端口设定。这样可不必构造一个完整的DCB结构。

下面介绍几个主要的函数和结构体:

(1)GetCommState

BOOL GetCommState( hCommDev, lpdcb);

参数hCommDev标识通信设备,应使用CreateFile返回的句柄。Lpdcb是指向DCB结构的指针,函数调用后当前串口配置信息将被保存在这个结构内。如果函数成功返回值为TRUE;否则返回值为FALSE。SetCommState用法与GetCommState相似,在此不再重复。DCB结构定义如下(只介绍主要的几项):

typedef struct _ DCB

……

DWORD BardRate; //波特率的设置

BYTE ByteSize; //数据位的个数

BYTE Parity; //是否有奇偶校验位

BYTE StopBits; //停止位的个数

……

DCB;

(2)SetCommTimeouts

BOOL SetCommTimeouts( hCommDev, lpctmo );

Lpctmo指向包含新的超时参数的COMMTIMEOUTS结构。COMMTIMEOUTS结构定义如下:

typedef struct _ COMMTIMEOUTS

DWORD ReadIntervalTimeout;

DWORD ReadTotalTimeoutMultiplier;

DWORD ReadTotalTimeoutconstant;

DWORD WriteTotalTimeoutMultiplier;

DWORD WriteTotalTimeoutconstant;

COMMTIMEOUTS, LPCOMMTIMEOUTS;

ReadIntervalTimeout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间。在ReadFile操作其间,收到第一个字符时开始计算时间。若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据。0值表示不用间隔限时。若该成员为MAXDWORD,且ReadTotalTimeoutconstant和ReadTotalTimeoutMultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回。

ReadTotalTimeoutMultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间。每个读操作的总限时时间等于读操作所需的字节数与该值的乘积。

ReadTotalTimeoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间。每个操作的总限时时间等于ReadTotalTimeoutMultiplier成员乘以读操作所需字节数再加上该值的和。ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant成员的值为0表示读操作不使用限时时间。

WriteTotalTimeoutMultiplier和WriteTotalTimeoutconstant的意义和作用分别与ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant相似,不再重复。

(3)BuilderCommDCB

BOOL BuilderCommDCB(lpszDef,lpdcb)

这个函数按lpszDef字符串所指定的格式来配置串口的DCB。
LpszDef:指向一个以NULL结束的字符串,该字符串指定串口的控制信息。比如,“1200,N,8,1”指定波特率为1200,无奇偶校验位,有8个数据位和1个停止位。

lpdcb:指向被填充的DCB结构。

(4)SetCommMask

BOOL SetCommMask(hCommDev,fdwEvtMask);

fdwEvtMask指向一个32位的屏蔽码,如果指定为EV_RXCHAR | EV_CTS,表示程序监控串口的收、发事件。

下面以简单的例子说明串口设置的步骤:

m_CommTimeouts.ReadIntervalTimeout = 1000;

m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;

m_CommTimeouts.ReadTotalTimeoutConstant = 1000;

m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;

m_CommTimeouts.WriteTotalTimeoutConstant = 1000;

if (SetCommTimeouts(m_hComm, &m_CommTimeouts))

// 串口超时参数设置

if (SetCommMask(m_hComm, dwCommEvents))

// 设置串口事件掩码

if (GetCommState(m_hComm, &m_dcb))

// 获取串口当前状态

if (BuildCommDCB(“1200,N,8,1”, &m_dcb))

// 建立串口设备控制块

if (SetCommState(m_hComm, &m_dcb));

// 设置串口参数

……

以上任何一个if语句的判断条件为假时都将调用GetLastError函数获取错误信息,进行错误处理。

4、读写串口数据

Win32API函数ReadFile和WriteFile支持对串行口 的读写操作。这些函数的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响。串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的。

在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序。

而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行。程序在调用ReadFile和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动的事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程。

通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数。

下面介绍主要的用于串口读写的函数:

(1)ReadFile 函数的调用方法如下:

BOOL ReadFile (

HANDLE hFile, //用CreateFile 获得的文件句柄

LPVOID lpBuffer, //输入缓冲区首址

DWORD nNumberOfBytesToRead,//设定读入字节数

LPDWORD lpNumberOfByteRead, //实际读入字节数

LPOVERLAPPED lpOverlapped //重叠操作方式数据结构地址

);

(2)WriteFile函数的调用方法如下:

BOOL WriteFile(

HANDLE hFile, //用CreateFile 获得的文件句柄

LPCVOID lpBuffer, //输出缓冲区首址

DWORD nNumberOfBytesToWrite, //要求输出的字节数

LPDWORD lpNumberOfBytesWritten,//实际输出字节数

LPOVERLAPPED lpOverlapped): //重叠操作方式数据结构地址

(3)GetOverlappedResult函数调用方法如下:

BOOL GetOverlappedResult(

HANDLE hFile, //用CreateFile 获得的文件句柄

LPOVERLAPPED lpOverlapped,

//指向一个在启动重叠操作时指定的

OVERLAPPED结构(即读写函数中指定的OverLapped结构)

LPDWORD lpNumberOfBytesTransferred,//实际传输的字节数

BOOL bWait, //是否等待悬挂的重叠操作完成,若为

//TRUE,则此函数直到操作完成后才返回。

);

OVERLAPPED结构定义如下:

typedef struct _OVERLAPPED

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent;

OVERLAPPED;

如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位)。

(4)WaitCommEvent函数的调用法如下:

BOOL WaitCommEvent(

HANDLE hCommDev, //串口句柄

LPDWORD lpfdwEvtMask, //见SetCommEvent函数说明

LPOVERLAPPED lpo, //重叠操作方式数据结构地址

);

当由SetCommMask函数所指定的事件产生时这个函数将返回TRUE。

下面是一个串口读写的流程图。

串口操作流程图

5、关闭串口

如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口。如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭。但为了安全起见,最好是显式的关闭它。关闭串口的语句为CloseHandle(hCommDev);其中hCommDev为用CreateFile建立的串口句柄。

6、一个完整的例子

这个串口控制类是我做的一个软件中使用的,基本用WINAPI实现,在Win95/Win98/Win2000下运行良好 ,可不做修改的用在其它BCB程序中 。读数据采用事件驱动方式,用一个线程处理相应事件,收到的字符用消息发往父窗口;由于我编的软件中写串口的数据不多,所以采用直接写的方式,而没用线程。

串口控制类 COM.h COM.cpp

串口控制类中使用的读串口线程 COMThread.h COMThread.cpp

打包下载

这个类的使用方法如下:

1、建立串口类的实例,如:

SerialPort=new TSerialPort(); //实例化一个串口控制类

//初始化串口,Baud:9600,DataBits:8,StopBits:1,无校验位

SerialPort->InitPort(this,g_iSerialPort,9600);

SerialPort->StartMonitoring(); //创建串口监控线程,开始监控

2、接收串口数据

(1)映射串口消息,在创建以上实例的窗口类的声明中加入:

void __fastcall OnComRx(TMessage &Message);

//指定消息WM_COMM_RXCHAR(由串口监控线程发出的消息,表示接收到一个字符)的处理函数为OnComRx

BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(WM_COMM_RXCHAR, TMessage, OnComRx)

END_MESSAGE_MAP(TForm)

(2)实现函数OnComRx(),如:

//---------------------------------------------------------------------------

//串口消息(接收到一个字符)处理函数

//消息的参数WParam就是接收到的字符

void __fastcall TDlgProgram::OnComRx(TMessage &Message)



unsigned char ucRxData=(unsigned char)Message.WParam; //串口监控线程收到的字符

………………



//---------------------------------------------------------------------------

3、向串口发送数据

调用函数bool WriteToPort(unsigned char ucTxChar)可向串口写一个字符。

如SerialPort->WriteToPort(0x55);本回答被提问者采纳

以上是关于在C语言中如果已经知道了一个数据的内存地址,怎样直接从内存中读取出该数据?的主要内容,如果未能解决你的问题,请参考以下文章

c语言问题:c语言中二维数组在内存中怎样存储?

怎样获取串口地址

C语言 读取文件到内存

C语言里怎样理解长整型 短整型 和无符号型变量和常量?

C语言 内存和地址

关于C语言的 变量 地址 和 值