在 C 中将 sizeof() 与指向结构的指针一起使用
Using sizeof() with pointer to struct in C
我现在正在学习 C,在尝试我的 uni 课程中的一些代码片段时遇到了一个小问题。
这是关于指向结构的 typedef 指针及其在 sizeof()
函数中的用法。
#include <stdio.h>
#include <stdlib.h>
// Define struct
struct IntArrayStruct
{
int length;
int *array;
};
// Set typedef for pointer to struct
typedef struct IntArrayStruct *IntArrayRef;
// Declare function makeArray()
IntArrayRef makeArray(int length);
// Main function
int main(void)
{
// Use makeArray() to create a new array
int arraySize = 30;
IntArrayRef newArray = makeArray(arraySize);
}
// Define makeArray() with function body
IntArrayRef makeArray(int length)
{
IntArrayRef newArray = malloc(sizeof(*IntArrayRef)); // ERROR
newArray->length = length;
newArray->array = malloc(length * sizeof(int));
return newArray;
}
并且 代码在 class 中使用的 IDE 中确实有效 (Virtual C),但是当我尝试完全相同的示例时在 VSCode 中使用 GNU Make 或 GCC 编译它,它 returns 一个错误,因为 malloc()
函数调用中的 sizeof(*IntArrayRef)
被标记为一个意外的类型名称。
error: unexpected type name 'IntArrayRef': expected expression
然而,当我将其更改为 sizeof(IntArrayStruct)
时,一切正常。
*IntArrayRef
和 IntArrayStruct
的值不一样吗?
IntArrayRef
是类型的名称,因此 *IntArrayRef
是无效语法。您可以(并且应该)做的是给出变量的名称并取消引用:
IntArrayRef newArray = malloc(sizeof(*newArray));
以下是您的类型名称之间的相互关系:
struct IntArrayStruct * == IntArrayRef
因此,newArray
的类型 IntArrayRef
与 struct IntArrayStruct *
相同
因此,如果您想要 pointer 类型的大小,您可以使用
之一
sizeof (IntArrayRef)
sizeof (struct IntArrayStruct *)
sizeof newArray
如果您想要指向类型(实际结构类型)的大小,您可以使用
之一
sizeof (struct IntArrayStruct)
sizeof *newArray
sizeof
是一个运算符,而不是一个函数 - 仅当操作数是类型名称(包括 typedef 名称)时才需要括号。在像 sizeof (*newArray)
这样的非类型操作数周围使用括号 没有什么坏处 ,但它们不是必需的。
作为风格说明,将指针类型隐藏在 typedef 后面通常不是一个好主意,尤其是当该类型的用户必须知道它是指针类型才能正确使用它时。 IOW,如果该类型的用户必须取消引用某些内容,那么该内容的指针应该是明确的。即使用户 不需要 需要显式取消引用它,你仍然不应该隐藏类型的指针(将标准库中的 FILE *
类型作为举个例子——你从来没有真正取消引用一个 FILE *
对象,但它的指针仍然是明确的)。
否则,请准备好编写一个完整的 API 对用户隐藏所有指针操作。
比较
sizeof(IntArrayStruct*)
sizeof(IntArrayRef)
对
sizeof(IntArrayStruct)
前两个是一样的,都是指针的大小。 IE。与 sizeof(int*)、sizeof(long*)、sizeof(void*) 等相同
第三个是实际数据结构的大小。如果您使用 malloc 为它创建 space,这就是您想要的。
此外,指针和引用在 C++ 中是两种不同的东西,因此使用缩写“ptr”来传达指针这一事实可能不会造成混淆。
最后,如前所述,创建新类型名称只是为了表示指向结构类型的指针,这是非标准的。这会混淆其他人而没有太大好处。
我现在正在学习 C,在尝试我的 uni 课程中的一些代码片段时遇到了一个小问题。
这是关于指向结构的 typedef 指针及其在 sizeof()
函数中的用法。
#include <stdio.h>
#include <stdlib.h>
// Define struct
struct IntArrayStruct
{
int length;
int *array;
};
// Set typedef for pointer to struct
typedef struct IntArrayStruct *IntArrayRef;
// Declare function makeArray()
IntArrayRef makeArray(int length);
// Main function
int main(void)
{
// Use makeArray() to create a new array
int arraySize = 30;
IntArrayRef newArray = makeArray(arraySize);
}
// Define makeArray() with function body
IntArrayRef makeArray(int length)
{
IntArrayRef newArray = malloc(sizeof(*IntArrayRef)); // ERROR
newArray->length = length;
newArray->array = malloc(length * sizeof(int));
return newArray;
}
并且 代码在 class 中使用的 IDE 中确实有效 (Virtual C),但是当我尝试完全相同的示例时在 VSCode 中使用 GNU Make 或 GCC 编译它,它 returns 一个错误,因为 malloc()
函数调用中的 sizeof(*IntArrayRef)
被标记为一个意外的类型名称。
error: unexpected type name 'IntArrayRef': expected expression
然而,当我将其更改为 sizeof(IntArrayStruct)
时,一切正常。
*IntArrayRef
和 IntArrayStruct
的值不一样吗?
IntArrayRef
是类型的名称,因此 *IntArrayRef
是无效语法。您可以(并且应该)做的是给出变量的名称并取消引用:
IntArrayRef newArray = malloc(sizeof(*newArray));
以下是您的类型名称之间的相互关系:
struct IntArrayStruct * == IntArrayRef
因此,newArray
的类型 IntArrayRef
与 struct IntArrayStruct *
因此,如果您想要 pointer 类型的大小,您可以使用
之一sizeof (IntArrayRef)
sizeof (struct IntArrayStruct *)
sizeof newArray
如果您想要指向类型(实际结构类型)的大小,您可以使用
之一sizeof (struct IntArrayStruct)
sizeof *newArray
sizeof
是一个运算符,而不是一个函数 - 仅当操作数是类型名称(包括 typedef 名称)时才需要括号。在像 sizeof (*newArray)
这样的非类型操作数周围使用括号 没有什么坏处 ,但它们不是必需的。
作为风格说明,将指针类型隐藏在 typedef 后面通常不是一个好主意,尤其是当该类型的用户必须知道它是指针类型才能正确使用它时。 IOW,如果该类型的用户必须取消引用某些内容,那么该内容的指针应该是明确的。即使用户 不需要 需要显式取消引用它,你仍然不应该隐藏类型的指针(将标准库中的 FILE *
类型作为举个例子——你从来没有真正取消引用一个 FILE *
对象,但它的指针仍然是明确的)。
否则,请准备好编写一个完整的 API 对用户隐藏所有指针操作。
比较
sizeof(IntArrayStruct*)
sizeof(IntArrayRef)
对
sizeof(IntArrayStruct)
前两个是一样的,都是指针的大小。 IE。与 sizeof(int*)、sizeof(long*)、sizeof(void*) 等相同
第三个是实际数据结构的大小。如果您使用 malloc 为它创建 space,这就是您想要的。
此外,指针和引用在 C++ 中是两种不同的东西,因此使用缩写“ptr”来传达指针这一事实可能不会造成混淆。
最后,如前所述,创建新类型名称只是为了表示指向结构类型的指针,这是非标准的。这会混淆其他人而没有太大好处。