C 为int*动态分配100字节,然后尝试使用指针算法为其设置值,会产生什么效果?

C 为int*动态分配100字节,然后尝试使用指针算法为其设置值,会产生什么效果?,c,pointers,malloc,pointer-arithmetic,C,Pointers,Malloc,Pointer Arithmetic,在我最近得到的一个测试中,它有一个问题,大意是“假设这段代码可以编译,它会做什么?” 代码: 我已经编写了代码并运行了它,当使用printf(%d,*x)打印时,结果是120,ascii值为x。我知道int必须被设置为x,当它被打印为int时,ascii值被打印出来,但是当涉及到malloc的实际效果是什么,以及所有的*(ptr+I)实际上做了什么时,我感到困惑。malloc()的实际效果是,使语句*ptr='x'和子序列访问实际上是有效的 如果没有内存分配,尝试取消引用指针将调用 也就是说

在我最近得到的一个测试中,它有一个问题,大意是“假设这段代码可以编译,它会做什么?”

代码:

我已经编写了代码并运行了它,当使用
printf(%d,*x)
打印时,结果是120,ascii值为x。我知道int必须被设置为x,当它被打印为int时,ascii值被打印出来,但是当涉及到malloc的实际效果是什么,以及所有的
*(ptr+I)
实际上做了什么时,我感到困惑。

malloc()的实际效果是,使语句
*ptr='x'和子序列访问实际上是有效的

如果没有内存分配,尝试取消引用指针将调用

也就是说

  • 在尝试取消引用返回的指针之前,必须检查
    malloc()
    是否成功
  • 指针算法接受数据类型。所以,像
    (ptr+1)
    这样的表达式指向下一个整数的内存位置,而不是内存的下一个字节。因此,表达式
    (ptr+)
    的RHS的任何
    n>24
    都将调用UB
  • 假设
    25*sizeof(int)
    =
    100字节
    ,这是非常具体的实现。如果
    sizeof(int)
    小于4个字节,您最终将访问指针算法中的绑定外内存(即使您将指针别名为
    char*
malloc()的实际效果是,做出声明
*ptr='x'和子序列访问实际上是有效的

如果没有内存分配,尝试取消引用指针将调用

也就是说

  • 在尝试取消引用返回的指针之前,必须检查
    malloc()
    是否成功
  • 指针算法接受数据类型。所以,像
    (ptr+1)
    这样的表达式指向下一个整数的内存位置,而不是内存的下一个字节。因此,表达式
    (ptr+)
    的RHS的任何
    n>24
    都将调用UB
  • 假设
    25*sizeof(int)
    =
    100字节
    ,这是非常具体的实现。如果
    sizeof(int)
    小于4个字节,您最终将访问指针算法中的绑定外内存(即使您将指针别名为
    char*

在C语言中,数组和指针非常相似,为了简单起见,在本例中可以方便地将它们视为相同的。因此,您可以将
malloc
视为动态分配25个整数的数组(例如,与动态地说
int ptr[25]
相同),也可以将其视为在内存中阻塞25个连续整数地址并将其标记为有效。这样,
ptr==&ptr[0]
。解引用运算符,
*
,表示“更改存储在此地址的值”,它实际上是“撤消”运算符。所以,
*ptr==*(&ptr[0])==ptr[0]
。此命令只是将ptr[0]设置为等于“x”,其ASCII值为120(并且将作为ASCII值打印,因为数组的类型为“int”,而不是“char”)。其余的作业也会这样做。根据编译器和操作系统的不同,超过ptr+24的任何内容都可能导致分段错误或写入无效,因为您只分配了25个整数,因此(ptr+99)不应是可写地址。如果只分配了25个插槽,您就不能编辑ptr[99]

在C中,数组和指针非常相似,为了简单起见,在这种情况下,可以方便地将它们视为相同的。因此,您可以将
malloc
视为动态分配25个整数的数组(例如,与动态地说
int ptr[25]
相同),也可以将其视为在内存中阻塞25个连续整数地址并将其标记为有效。这样,
ptr==&ptr[0]
。解引用运算符,
*
,表示“更改存储在此地址的值”,它实际上是“撤消”运算符。所以,
*ptr==*(&ptr[0])==ptr[0]
。此命令只是将ptr[0]设置为等于“x”,其ASCII值为120(并且将作为ASCII值打印,因为数组的类型为“int”,而不是“char”)。其余的作业也会这样做。根据编译器和操作系统的不同,超过ptr+24的任何内容都可能导致分段错误或写入无效,因为您只分配了25个整数,因此(ptr+99)不应是可写地址。如果您只分配了25个插槽,您应该无法编辑
ptr[99]

Oups,C指针算法基于定义
*(ptr+i)
is
ptr[i]

这意味着,当您为25个整数分配空间时,所有超过第24个元素的访问都将调用未定义的行为——您实际上试图访问一个您不知道它代表什么的内存

但是,只要使用指向char(或无符号char)的指针,就可以在字节级别访问任何对象。因此,假设在编译器中sizeof(int)为4,则可以:

int *iptr;
char *cptr;
iptr = malloc( 25 * sizeof(int)); //100 bytes since we know that sizeof(int) is 4
cptr = (char *) iptr; // cast of pointer to any to pointer to char is valid
for(int i=0; i<25*sizeof(int); i++) cptr[i] = 'x'; // store chars 'x'
for(int i=0; i<25; i++) {
    printf(" %x", (unsigned int) iptr[i]);  // print the resulting ints in hexa
}
printf("\n");
int*iptr;
char*cptr;
iptr=malloc(25*sizeof(int))//100字节,因为我们知道sizeof(int)是4
cptr=(字符*)iptr;//将指针强制转换为指向char的任何指针都是有效的

对于(int i=0;iOups,C指针算法基于定义
*(ptr+i)
is
ptr[i]

这意味着,当您为25个整数分配空间时,所有超过第24个元素的访问都将调用未定义的行为——您实际上试图访问一个您不知道它代表什么的内存

但事实确实如此
int *iptr;
char *cptr;
iptr = malloc( 25 * sizeof(int)); //100 bytes since we know that sizeof(int) is 4
cptr = (char *) iptr; // cast of pointer to any to pointer to char is valid
for(int i=0; i<25*sizeof(int); i++) cptr[i] = 'x'; // store chars 'x'
for(int i=0; i<25; i++) {
    printf(" %x", (unsigned int) iptr[i]);  // print the resulting ints in hexa
}
printf("\n");
     +---+
ptr: |   | ----> ???
     +---+
     +---+
ptr: |   | ---+
     +---+    |
      ...     |
       +------+
       |
       V
     +---+
     |   | ptr[0]
     +---+
     |   | ptr[1]
     +---+
      ...
T *p = malloc( N * sizeof *p );
*ptr = 'x';
*(ptr + 1) = 'x';
ptr[0] = 'x';
ptr[1] = 'x';
*(ptr +99) = 'x';