繁体   English   中英

关于C中的静态和动态数组的困惑

[英]Confusion about static and dynamic arrays in C

typedef struct mystruct{
  int a;
  char arr[10];
  char *str;
}mystruct;


void f(void *data, int offset){
  char *s = (char *)(data + offset);
  printf("%s", s);
}

void g(void *data, int offset){
  char *s = *(char **)(data+offset);
  printf("%s", s);
}

int main(){
  mystruct test;
  test.a = 2;
  test.str = malloc(100);
  strcpy(test.arr, "Hello ");
  strcpy(test.str, "World!");
  f(&test, offsetof(mystruct,arr));
  g(&test, offsetof(mystruct,str));
  return 0;
}

我想知道为什么我需要两种不同的方式来打印字符串。 在函数f中 ,实际指向的是什么(数据+偏移量)? 是不是指向arr哪个是指向字符串第一个元素的char指针? 但是在函数g中 ,(data + offset)也指向了char指针。 那么为什么必须使用两种不同的方法来完成同样的任务呢?

在这两种情况下, data+offset指向结构成员

但是让我们看看结构的结构。 它包括

+-----+--------------------------------------------+
| a   | sizeof(int) probably 4 or 8 bytes          |
+-----+--------------------------------------------+
| possible padding of unknown size (probably zero) |
+-----+--------------------------------------------+
| arr | 10 bytes                                   |
+-----+--------------------------------------------+
| possible padding of unknown size (maybe 2 bytes) |
+-----+--------------------------------------------+
| str | sizeof(char*) probably 4 or 8 bytes        |
+-----+--------------------------------------------+

内存中的其他地方是用malloc分配的100字节块。

请注意,对于数据test.arr存储分配内存test ,而是存储在事test对于test.str是另一个内存块的地址。

你必须给编译器提供有关函数fg中指针类型的信息,你不能对void指针进行点运算。

data转换为char指针,printf将起作用

void f(void *data, int offset){
  char *s = (char *)(( char*)data + offset); 
  printf("%s", s);
}

void g(void *data, int offset){
  char *s = *(char **)((char*)data+offset);   
  printf("%s", s);
}

在函数f ,实际指向的是什么(data + offset) 是不是指向arr哪个是指向字符串第一个元素的char指针?

这是您混淆的主要原因。 arr不是指针,它是一个数组。 数组不是指针。 同时, str是一个指针。 “数组”和“指针”是两个完全不同的东西。 他们几乎没有任何共同之处。 这正是您必须以不同方式使用它们的原因。

在所谓的值上下文中 (即当用作rvalues时 ),数组和指针的行为非常相似,但这纯粹是肤浅的相似性。 他们立即揭示了他们在所谓的对象上下文中的主要差异(即当用作左值时 )。 在您的特定示例中,您的成员访问代码是对象上下文的示例,这就是您必须仔细观察arrstr之间差异的原因。

数组和指针之间的差异问题已经涵盖了很多次。 我认为没有理由在此重复。 只需在SO上搜索“数组指针差异”即可。 或者阅读必要的FAQ

http://c-faq.com/aryptr/index.html

PS还要注意C语言不支持void *指针上的指针算法。 您的所有(data + offset)表达式都无效。 你想要做的是((char *) data + offset) 为了能够使用字节偏移执行点算术,需要将datavoid *转换为char *

在你的结构中,在(推测)偏移4处,是一个一个接一个的10个字节的列表,包含制作'Hello'的字母; 所以(data + 4)是char的指针,需要相应地进行dcoded(即char * )。

然而,在那10个字节之后,来一些字节使缓冲区的地址在某处,即那些字节是'char *'(你定义它们),所以数据+偏移有一个指针在char指针或一个char **

可能令人困惑的是两者兼而有之

strcpy(test.arr,“你好”);
strcpy(test.str,“World!”);

工作。

这是一个令人困惑的(但很有用的C / C ++特性)。 当数组的名称在需要指向数组元素类型的指针的位置中使用时,编译器将对其进行处理,就像它是指向数组的第一个元素的指针一样。

所以test.str显然是一个指向char的指针(因为你这样定义)。 如果情况表明, test.arr 可以用作指向第一个测试元素的指针。

当你写strcpy(test.arr, "Hello "); 编译器假设你的意思是strcpy(&test.arr[0], "Hello ");

在函数f中,实际指向的是什么(数据+偏移量)?

它指向结构对象的'arr'成员(如果你假设GCC的void指针算术的语义)。

是不是指向arr哪个是指向字符串第一个元素的char指针?

arr是一个char数组,而不是char指针。

但是在函数g中,(data + offset)也指向了char指针。

在这种情况下,它指向一个char指针,是的。

那么为什么必须使用两种不同的方法来完成同样的任务呢?

指针指向两个不同的东西 - 一个指向char指针(它本身指向一个char数组),另一个指向char数组。 在第一种情况下还有一个间接级别。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM