我最近学习了nios II SOPC,我遇到了写入和读取内存的过程。指针int *和char *的使用让我有两个不同的结果。代码如下。
#include "system.h"
#include "stdio.h"
int main()
{
char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
int i;
for(i=0;i<16;i++)
{
*(n+i)=i;
}
for(i=0;i<16;i++)
{
printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
}
while(1);
}
“int *”的代码如下
#include "system.h"
#include "stdio.h"
int main()
{
char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
int i;
for(i=0;i<16;i++)
{
*(n+i)=i;
}
for(i=0;i<16;i++)
{
printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
}
while(1);
}
使用“int *”的结果是0,1,2,...,15,而“char *”的结果是3,3,3,3,7,7,7,7,11, 11,11,11,15,15,15,15。我无法解释为什么会这样。
以下是我的内存块代码
module memory
#(parameter DATA_WIDTH=32, parameter ADDR_WIDTH=4)
(
input iClk, iReset_n,
input iRead_n, iWrite_n,
input [ADDR_WIDTH-1:0] iAddress,
input [DATA_WIDTH-1:0] iData,
output [DATA_WIDTH-1:0] oData
);
reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0] addr_reg;
always@(posedge iClk)
begin
if(!iWrite_n)
mem[iAddress] = iData;
if(!iRead_n)
addr_reg = iAddress;
end
assign oData = mem[addr_reg];
endmodule
答案 0 :(得分:2)
这是我根据观察到的行为进行的推测。
您的存储设备由16 x 32位整数组成。我的推测是,喜欢以字节为单位处理事物的编译器实际上屏蔽了地址的最低两位。第零个寄存器的地址为MEMORY_0_BASE + 0 * 4
,第一个寄存器的地址为MEMORY_0_BASE + 1 * 4
,第二个寄存器的地址为MEMORY_0_BASE + 2 * 4
等。
如果使用int指针将int存储到寄存器中,每次递增int指针时,C指针算术实际上会将sizeof(int)
= 4添加到指针中的地址,因此地址序列int存储如上所述。
如果使用char指针存储字符,则每次递增char指针时,C指针算术会将sizeof(char)
= 1添加到指针中的地址。代码尝试将前四个字符(0,1,2,3)存储到MEMORY_0_BASE + 0
,MEMORY_0_BASE + 1
,MEMORY_0_BASE + 2
,MEMORY_0_BASE + 3
。如果我相信指针的底部两位被屏蔽,那么所有这些地址都存储到MEMORY_0_BASE
,并且当你完成时,它的值是3。
类似于后四个字符(4,5,6,7)。它们会存储到MEMORY_0_BASE + 4
,MEMORY_0_BASE + 5
,MEMORY_0_BASE + 6
,MEMORY_0_BASE + 7
,这些都会在屏蔽后映射到MEMORY_0_BASE + 4
,并使其包含数字7,依此类推。
这就是你如何得到序列3,3,3,3,7,7,7,7,11,11,11,11,15,15,15,15。