关于数组越界与地址,大家看看这几行代码的执行结果是什么?

ooolinux 2017-08-23 06:18:34
int _tmain(int argc, _TCHAR* argv[])
{
int a;
int b[3];
int c;
printf("%p\n",&a);
for(int i=-1;i<=3;i++)
printf("%p\n",&b[i]);
printf("%p\n",&c);
return 0;
}


我用VS2010 Express貌似得不到想要的结果。
...全文
529 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-08-29
  • 打赏
  • 举报
回复
pack #pragma pack( [ n] ) Specifies packing alignment for structure and union members. Whereas the packing alignment of structures and unions is set for an entire translation unit by the /Zp option, the packing alignment is set at the data-declaration level by the pack pragma. The pragma takes effect at the first structure or union declaration after the pragma is seen; the pragma has no effect on definitions. When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each structure member after the first is stored on the smaller member type or n-byte boundaries. If you use #pragma pack without an argument, structure members are packed to the value specified by /Zp. The default /Zp packing size is /Zp8. The compiler also supports the following enhanced syntax: #pragma pack( [ [ { push | pop}, ] [ identifier, ] ] [ n ] ) This syntax allows you to combine program components into a single translation unit if the different components use pack pragmas to specify different packing alignments. Each occurrence of a pack pragma with a push argument stores the current packing alignment on an internal compiler stack. The pragma’s argument list is read from left to right. If you use push, the current packing value is stored. If you provide a value for n, that value becomes the new packing value. If you specify an identifier, a name of your choosing, the identifier is associated with the new packing value. Each occurrence of a pack pragma with a pop argument retrieves the value at the top of an internal compiler stack and makes that value the new packing alignment. If you use pop and the internal compiler stack is empty, the alignment value is that set from the command-line and a warning is issued. If you use pop and specify a value for n, that value becomes the new packing value. If you use pop and specify an identifier, all values stored on the stack are removed from the stack until a matching identifier is found. The packing value associated with the identifier is also removed from the stack and the packing value that existed just before the identifier was pushed becomes the new packing value. If no matching identifier is found, the packing value set from the command line is used and a level-one warning is issued. The default packing alignment is 8. The new, enhanced functionality of the pack pragma allows you to write header files that ensure that packing values are the same before and after the header file is encountered: /* File name: include1.h */ #pragma pack( push, enter_include1 ) /* Your include-file code ... */ #pragma pack( pop, enter_include1 ) /* End of include1.h */ In the previous example, the current pack value is associated with the identifier enter_include1 and pushed, remembered, on entry to the header file. The pack pragma at the end of the header file removes all intervening pack values that may have occurred in the header file and removes the pack value associated with enter_include1. The header file thus ensures that the pack value is the same before and after the header file. The new functionality also allows you to use code, such as header files, that uses pack pragmas to set packing alignments that differ from the packing value set in your code: #pragma pack( push, before_include1 ) #include "include1.h" #pragma pack( pop, before_include1 ) In the previous example, your code is protected from any changes to the packing value that might occur in include.h.
Remove_ 2017-08-28
  • 打赏
  • 举报
回复
引用 10 楼 u010165006 的回复:
[quote=引用 8 楼 Chen_QiDian 的回复:] 栈上存储数据是连续的,这点毋庸置疑。 但是楼主写的例子结果可这样解释: debug版本在每个变量两边增加了,若干数据,变量尺寸变大了。int如果是4字节,经过debug后实际上分配了12字节,左右各4字节。实际按照12字节算的话还是连续的
debug版应该是这样的。
引用 9 楼 wwww200808008 的回复:
楼主的意思估计是 他获取的地址虽然越界了,但是根据连续分配的规则,数组-1下标的地址应当和c一样 ,但是结果却不是?那你可以用release看看,因为debug的话他分配变量的时候会多分配一些供调试信息存储。我是这么理解的。
我用VS2010 Express编译成release版,b[-1]的地址和c的地址一样,但是b[3]的地址和a的地址差很多,很难理解。 [/quote] 你用release编译,他肯定会帮你优化内存的排序啦,所以他的内存不是按你声明来排序的,他在内存中是 a c b[0] b[1] b[2]
ooolinux 2017-08-28
  • 打赏
  • 举报
回复
引用 14 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("AD sizeof %d\n", sizeof(AD));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("A1 sizeof %d\n", sizeof(A1));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("A2 sizeof %d\n", sizeof(A2));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("A4 sizeof %d\n", sizeof(A4));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("A8 sizeof %d\n", sizeof(A8));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("A16 sizeof %d\n", sizeof(A16));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//AD sizeof 32
//
//A1.a 0
//A1.b 4
//A1.c 17
//A1 sizeof 25
//
//A2.a 0
//A2.b 4
//A2.c 18
//A2 sizeof 26
//
//A4.a 0
//A4.b 4
//A4.c 20
//A4 sizeof 28
//
//A8.a 0
//A8.b 4
//A8.c 24
//A8 sizeof 32
//
//A16.a 0
//A16.b 4
//A16.c 24
//A16 sizeof 32
//
//
老赵这个离题了~
ooolinux 2017-08-28
  • 打赏
  • 举报
回复
引用 13 楼 wwww200808008 的回复:
你用release编译,他肯定会帮你优化内存的排序啦,所以他的内存不是按你声明来排序的,他在内存中是 a c b[0] b[1] b[2]
应该是这样的。
赵4老师 2017-08-28
  • 打赏
  • 举报
回复
仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("AD sizeof %d\n", sizeof(AD));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("A1 sizeof %d\n", sizeof(A1));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("A2 sizeof %d\n", sizeof(A2));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("A4 sizeof %d\n", sizeof(A4));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("A8 sizeof %d\n", sizeof(A8));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("A16 sizeof %d\n", sizeof(A16));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//AD sizeof 32
//
//A1.a 0
//A1.b 4
//A1.c 17
//A1 sizeof 25
//
//A2.a 0
//A2.b 4
//A2.c 18
//A2 sizeof 26
//
//A4.a 0
//A4.b 4
//A4.c 20
//A4 sizeof 28
//
//A8.a 0
//A8.b 4
//A8.c 24
//A8 sizeof 32
//
//A16.a 0
//A16.b 4
//A16.c 24
//A16 sizeof 32
//
//
ooolinux 2017-08-25
  • 打赏
  • 举报
回复
引用 1 楼 sdghchj 的回复:
你想要啥结果
越界的地址和变量a、c的地址不太一样。
ooolinux 2017-08-25
  • 打赏
  • 举报
回复
引用 4 楼 MoshangYanYu 的回复:
for(int i=-1;i<=3;i++) printf("%p\n",&b[i]); 越界了啊。。。你int b[3];长度只有3.。。可是循环超过了3次。。。越界了。。。另外楼主要啥结果
越界的地址和变量a、c的地址不太一样。
MoshangYanYu 2017-08-25
  • 打赏
  • 举报
回复
for(int i=-1;i<=3;i++) printf("%p\n",&b[i]); 越界了啊。。。你int b[3];长度只有3.。。可是循环超过了3次。。。越界了。。。另外楼主要啥结果
ooolinux 2017-08-25
  • 打赏
  • 举报
回复
引用 11 楼 wyyy2088511 的回复:
http://blog.csdn.net/wyyy2088511/article/details/77337301 由该网址看到 :b[2]的地址是a的地址加12。b[3]地址是&a+8。 a的地址0025fe90,b[3]的地址是0025fe88,刚好差8。所以地址正常。
你这个是debug版,你试试release版。
jena_wy 2017-08-25
  • 打赏
  • 举报
回复
http://blog.csdn.net/wyyy2088511/article/details/77337301
由该网址看到 :b[2]的地址是a的地址加12。b[3]地址是&a+8。
a的地址0025fe90,b[3]的地址是0025fe88,刚好差8。所以地址正常。
ooolinux 2017-08-25
  • 打赏
  • 举报
回复
引用 8 楼 Chen_QiDian 的回复:
栈上存储数据是连续的,这点毋庸置疑。 但是楼主写的例子结果可这样解释: debug版本在每个变量两边增加了,若干数据,变量尺寸变大了。int如果是4字节,经过debug后实际上分配了12字节,左右各4字节。实际按照12字节算的话还是连续的
debug版应该是这样的。
引用 9 楼 wwww200808008 的回复:
楼主的意思估计是 他获取的地址虽然越界了,但是根据连续分配的规则,数组-1下标的地址应当和c一样 ,但是结果却不是?那你可以用release看看,因为debug的话他分配变量的时候会多分配一些供调试信息存储。我是这么理解的。
我用VS2010 Express编译成release版,b[-1]的地址和c的地址一样,但是b[3]的地址和a的地址差很多,很难理解。
Remove_ 2017-08-25
  • 打赏
  • 举报
回复
楼主的意思估计是 他获取的地址虽然越界了,但是根据连续分配的规则,数组-1下标的地址应当和c一样 ,但是结果却不是?那你可以用release看看,因为debug的话他分配变量的时候会多分配一些供调试信息存储。我是这么理解的。
Chen_QiDian 2017-08-25
  • 打赏
  • 举报
回复
栈上存储数据是连续的,这点毋庸置疑。 但是楼主写的例子结果可这样解释: debug版本在每个变量两边增加了,若干数据,变量尺寸变大了。int如果是4字节,经过debug后实际上分配了12字节,左右各4字节。实际按照12字节算的话还是连续的
sdghchj 2017-08-25
  • 打赏
  • 举报
回复
引用 6 楼 u010165006 的回复:
[quote=引用 1 楼 sdghchj 的回复:] 你想要啥结果
越界的地址和变量a、c的地址不太一样。[/quote] 怎么个不一样?你想要怎么个一样?会不会问问题?能表达清楚点吗? a、c本来就是不同的变量,地址当然不一样,不是不太一样,更不是一样! a、b、c的地址应该是在栈上连续的。
赵4老师 2017-08-24
  • 打赏
  • 举报
回复
http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素
ooolinux 2017-08-23
  • 打赏
  • 举报
回复
引用 1 楼 sdghchj 的回复:
你想要啥结果
release版,跟想的不一样。
sdghchj 2017-08-23
  • 打赏
  • 举报
回复
你想要啥结果

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧