藉助U-boot進行一些記憶體位址的再次研究(二維數組及指標數組)

來源:互聯網
上載者:User

轉自:http://www.latelee.org/porting-uboot/150-u-boot-porting-memory-again.html


#include <common.h>

#include <command.h>

int a[2][2] = {
{3,56},
{15,73},
};

char *b[] = {
"linux",
"windows",
"mac os",
};

char *c[][2] = {
{"linux", "unix"},
{"windows"},
{"mac os"},
};

int do_pointer_test(cmd_tbl_t *cmdtp,
int flag, int argc,
char * const argv[])
{
int i;
printf("sizeof a: %d sizeof b: %d sizeof c: %d\n\n",
sizeof(a), sizeof(b),
sizeof(c));
for (i=0;i<sizeof(a)/sizeof(int);i++)
printf("%p %p: %d\t %p: %d %p\n", a+i, *a+i, *(*a+i), a[i], *a[i], (void*)*a[i]);
printf("\n");
printf("&b[i] b+i b[i] b[i] *b+i\n");
for (i=0;i<sizeof(b)/sizeof(char*);i++)
printf("%p %p %p: %s\t %s\n", &b[i], b+i, b[i], b[i], *b+i);

printf("\n");
for (i=0;i<sizeof(c)/sizeof(char*);i++)
printf("%p %p: %s\n", c[i], *c[i], *c[i]);
printf("\n");
return 0;
}

U_BOOT_CMD(
pointer_test, 2, 1,do_pointer_test,
"just a test of my own",
"nothing"
);

在u-boot命令列下測試結果:

LATE2440
$ pointer_test
sizeof a: 16 sizeof b: 12 sizeof c: 24

33fa622c 33fa622c: 3 33fa622c: 3 00000003
33fa6234 33fa6230: 56 33fa6234: 15 0000000f
33fa623c 33fa6234: 15 33fa623c: 872036659 33fa3933
33fa6244 33fa6238: 73 33fa6244: 872038649 33fa40f9

&b[i] b+i b[i] b[i] *b+i
33fa623c 33fa623c 33fa3933: linux linux
33fa6240 33fa6240 33fa40f1: windows inux
33fa6244 33fa6244 33fa40f9: mac os nux

33fa6248 33fa3933: linux
33fa6250 33fa40f1: windows
33fa6258 33fa40f9: mac os
(此處死機)

數組a的大小好確認:4(成員個數)*4(int類型大小) = 16;數組b也好確認:3(成員個數)*4(指標大小) = 12;數組c是一個二維數組,元素為一指標,3組,每組2個元素,共6個元素,指標大小為4,因此大小為:6*4 = 24。

現在查看一下數組a所在的地址:

LATE2440
$ md.b 33fa622c
33fa622c: 03 00 00 00 38 00 00 00 0f 00 00 00 49 00 00 00 ....8.......I...
33fa623c: 33 39 fa 33 f1 40 fa 33 f9 40 fa 33 33 39 fa 33 39.3.@.3.@.339.3
33fa624c: 00 41 fa 33 f1 40 fa 33 00 00 00 00 f9 40 fa 33 .A.3.@.3.....@.3
33fa625c: 00 00 00 00 08 08 08 08 08 08 08 08 08 28 28 28 .............(((

其後有4個元素,分別為3、38、f和49,變成十進位則是3、56、15和73。

下面看一下數組b的地址:

LATE2440
$ md.b 33fa623c
33fa623c: 33 39 fa 33 f1 40 fa 33 f9 40 fa 33 33 39 fa 33 39.3.@.3.@.339.3
33fa624c: 00 41 fa 33 f1 40 fa 33 00 00 00 00 f9 40 fa 33 .A.3.@.3.....@.3
33fa625c: 00 00 00 00 08 08 08 08 08 08 08 08 08 28 28 28 .............(((
33fa626c: 28 28 08 08 08 08 08 08 08 08 08 08 08 08 08 08 ((..............

前面三個地址分別為:33fa3933、33fa40f1和33fa40f9,就是b[0]、b[1]和b[2]的地址,再看看這些地址:

LATE2440
$ md.b 33fa3933
33fa3933: 6c 69 6e 75 78 00 4c 69 6e 75 78 00 6e 65 74 62 linux.Linux.netb
33fa3943: 73 64 00 4e 65 74 42 53 44 00 72 74 65 6d 73 00 sd.NetBSD.rtems.
33fa3953: 52 54 45 4d 53 00 75 2d 62 6f 6f 74 00 55 2d 42 RTEMS.u-boot.U-B
33fa3963: 6f 6f 74 00 71 6e 78 00 51 4e 58 00 76 78 77 6f oot.qnx.QNX.vxwo

第一個字串便是“linux”。

LATE2440
$ md.b 33fa40f1
33fa40f1: 77 69 6e 64 6f 77 73 00 6d 61 63 20 6f 73 00 75 windows.mac os.u
33fa4101: 6e 69 78 00 70 6f 69 6e 74 65 72 5f 74 65 73 74 nix.pointer_test
33fa4111: 00 25 6c 6c 75 20 42 79 74 65 73 25 73 00 2e 25 .%llu Bytes%s..%
33fa4121: 6c 64 00 20 25 63 69 42 25 73 00 20 25 30 2a 78 ld.
%ciB%s. %0*x

前面兩個字串就是“windows”和“mac os”。

後面我們可以看到,在PC平台上,三者其實是緊挨在一起的。這裡只有後兩個字串是在一起(33fa40f1+8 = 33fa40f9)。這裡我們也可以看到字串在記憶體中是以“\0”結尾的(如“windows.”後的點號,實際資料是0),不過在代碼上體現不出來。以後我們要注意,在記憶體配置時需要對字串(指標)額外關照,至少要分配多一個位元組給它。

不過我們也看到了,這三個字串前面後面都有字串(u-boot本身的),如:

LATE2440
$ md.b 33fa3900
33fa3900: 52 43 20 36 34 20 42 69 74 00 62 6c 61 63 6b 66 RC 64 Bit.blackf
33fa3910: 69 6e 00 42 6c 61 63 6b 66 69 6e 00 61 76 72 33 in.Blackfin.avr3
33fa3920: 32 00 41 56 52 33 32 00 49 6e 76 61 6c 69 64 20 2.AVR32.Invalid
33fa3930: 4f 53 00 6c 69 6e 75 78 00 4c 69 6e 75 78 00 6e OS.linux.Linux.n

LATE2440 $ md.b 33fa40e0
33fa40e0: 09 20 25 73 0a 00 25 70 20 25 70 3a 20 25 73 0a .
%s..%p %p:
%s.
33fa40f0: 00 77 69 6e 64 6f 77 73 00 6d 61 63 20 6f 73 00 .windows.mac os.
33fa4100: 75 6e 69 78 00 70 6f 69 6e 74 65 72 5f 74 65 73 unix.pointer_tes
33fa4110: 74 00 25 6c 6c 75 20 42 79 74 65 73 25 73 00 2e t.%llu Bytes%s..

這說明了它們佔領了別人的“領域”,而且,在測試結果中我們意外地看到,*a[3]和*a[4]分別是b[0]和b[2]的地址,限於能力,這裡不作解釋,留日後技術提高了再研究。

下面是在PC平台(fedora9)的測試結果:

[latelee@FightNow linux-cc]$ ./a.out

sizeof a: 16 sizeof b: 12 sizeof c: 24

0x80498e4 0x80498e4: 3 0x80498e4: 3 0x3
0x80498ec 0x80498e8: 56 0x80498ec: 15 0xf
0x80498f4 0x80498ec: 15 0x80498f4: 134514372 0x80486c4
0x80498fc 0x80498f0: 73 0x80498fc: 134514386 0x80486d2

&b[i] b+i b[i] b[i] *b+i
0x80498f4 0x80498f4 0x80486c4: linux linux
0x80498f8 0x80498f8 0x80486ca: windows inux
0x80498fc 0x80498fc 0x80486d2: mac os nux

0x8049900 0x80486c4: linux
0x8049908 0x80486ca: windows
0x8049910 0x80486d2: mac os
0x8049918 (nil): (null)
0x8049920 (nil): (null)
0x8049928 (nil): (null)

最後幾行都列印了null,因為這的確是沒有資料的,不過在u-boot中就死機了。

用gdb查看:

(gdb) p b
$4 = {0x80486c4 "linux", 0x80486ca
"windows", 0x80486d2 "mac os"}

(gdb) p c
$1 = {{0x80486c4 "linux", 0x80486d9
"unix"}, {0x80486ca "windows", 0x0}, {
0x80486d2 "mac os", 0x0}}
(gdb)

(gdb) p &b
$5 = (char *(*)[3]) 0x80498f4

(gdb) p &a
$6 = (int (*)[2][2]) 0x80498e4
(gdb) p &a[1][1]
$9 = (int *) 0x80498f0
(gdb) p a[1][1]
$10 = 73
(gdb) p &a[1]
$12 = (int (*)[2]) 0x80498ec
(gdb) p a[1]
$13 = {15, 73}
(gdb)

PS:對於元素的訪問,array[i]與array+i不太一樣,跟具體類型有關,這從代碼中亦能看出來。

寫這篇文章的原因是在CU論壇上看到有人在討論二維數組的文章。看了一下他們的討論,發現自己啥也不懂,於是藉助u-boot來看看,結果發現,自己真的是不太懂。原來自己已經很久沒有看C語言的書籍了。看來最近忙著移植,沒時間看書了,一些基本概念也不清楚了。身為一個代碼工人,除了表示慚愧外,要努力學習了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.