Tag: 语言 律师

我是否有sizeof(type)== sizeof(无符号类型)的保证?

sizeof char,int,long double ……可能因编译器而异。 但是,根据C ++ 11或C11标准,我是否有任何有符号和无符号基本积分类型的大小相同的保证?

是(x ++,y)+(y ++,x)未定义或未指定,如果未指定,它可以计算什么?

逗号序列运算符在表达式中引入序列点 。 我想知道这是否意味着下面的程序避免了未定义的行为。 int x, y; int main() { return (x++, y) + (y++, x); } 如果它确实避免了未定义的行为,它仍然可能未指定,即返回几个可能值中的一个。 我认为在C99中,它只能计算1 ,但实际上,各种版本的GCC将这个程序编译成一个返回2的可执行文件。 Clang生成一个返回1的可执行文件,显然与我的直觉一致。 最后,这是C11改变了吗?

兼容类型并忽略C类型系统中的顶级限定符

这是一个多部分的问题。 我一直在努力了解C型系统。 首先,C标准提到了“兼容类型”一词,所以我试图理解这一点。 这个定义似乎很分散,但我发现: 6.2.7兼容类型和复合类型1如果类型相同,则两种类型具有兼容类型。 确定两种类型是否兼容的附加规则在6.7.2中描述了类型说明符,在6.7.3中描述了类型限定符,在6.7.6中描述了声明符.55)此外,两个结构,联合或枚举类型在单独声明如果翻译单元的标签和成员满足以下要求,则它们是兼容的:如果使用标签声明一个,则另一个应使用相同的标签声明。 如果两者都在各自的翻译单元内的任何地方完成,那么以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对相应的成员被宣布为兼容类型; 如果使用对齐说明符声明该对中的一个成员,则使用等效的对齐说明符声明另一个成员; 如果该对的一个成员使用名称声明,则另一个成员使用相同的名称声明。 对于两个结构,相应的成员应按相同的顺序声明。 对于两个结构或联合,相应的位域应具有相同的宽度。 对于两个枚举,相应的成员应具有相同的值。 REFS: 6.7.2 short == short int == signed short == signed short int, etc. 6.7.3 10) For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of […]

我们可以重用已分配的内存

这是对这个问题的跟进。 在解释我的问题时,我声明分配的内存可以重用,因为它没有声明的类型,我被告知它是不正确的C. 这是一个说明问题的代码示例: #include #include #include #include struct Elt { int id; char name[32]; }; struct Elt2 { double val; char name[16]; }; static_assert(sizeof(struct Elt2) id, elt->name); struct Elt2 *elt2 = (void *) elt; // declares a new pointer to a shorter type memcpy(elt2, &actual2, sizeof(*elt2)); // effective type is now struct Elt2 printf(“elt2: %g […]

实现可以指定未定义的行为

3.4.1 1实现定义的行为 未指定的行为,其中每个实现记录了如何进行选择 实现是否可以指定,在未定义的行为是可能的结果的情况下,实现定义的行为是未定义的行为? 例如: 6.3.1.3有符号和无符号整数 3否则,新类型已签名且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号。 因此,只要记录在案,这个结果是否可以由实现未定义并导致未定义的行为,或者它必须具有该实现的定义结果?

getc()作为宏和C标准库函数定义,连贯吗?

在[7.1.4库函数的使用]中 ,我读到: 标题中声明的任何函数可以另外实现为标题中定义的函数式宏… 和 任何实现为宏的库函数的调用都应扩展为仅对其每个参数进行一次计算的代码… 然后对于getc , [7.21.7.5 getc函数] : getc函数等效于fgetc,除非它实现为宏,它可能会多次评估流,因此参数永远不应该是带有副作用的表达式。 getc的定义是: 与库函数定义相矛盾? 反过来? 这是标准中的不连贯吗? 或者这是否意味着如果getc完全实现(似乎不符合但是?)作为宏,它可能会两次评估它的参数?

关于指针比较,标准中的措辞比较奇怪

§6.5.8\ 6 (关于>,<, =) 如果表达式P指向数组对象的元素并且表达式Q指向同一数组对象的最后一个元素,则指针表达式Q + 1比P大。 在所有其他情况下,行为未定义。 上面的几节,§6.5.8,它解释了基本上,指针算法在数组上按预期工作。 这是int a[3]; int *p = a; int *q = &a[2]; //qp == 3 int a[3]; int *p = a; int *q = &a[2]; //qp == 3 int a[3]; int *p = a; int *q = &a[2]; //qp == 3有效。 但是,当我读到上面的q > p是UB。 我错过了什么?

兼容类型和参数类型限定符

这两个声明的类型是否兼容? void f(char *, char *); void f(char *restrict, char *restrict); 或者类似的: void g(char *); void g(char *const); 我很难找到涵盖问题的标准中的任何内容。 我最感兴趣的是关于手动原型化函数是否有效的主题,省略了restrict关键字,其中实际类型可能具有限制限定的参数,具体取决于C的版本或正在使用的其他库的版本。

更改const对象 – 没有警告? 还有,在哪种情况下它是UB?

为什么以下代码中没有警告? int deserialize_students(const Student *dest, const int destCapacityMax) { FILE *ptr_file; int i=0; ptr_file =fopen(“output.txt”,”r”); if (!ptr_file) return -1; if(destCapacityMax==0) return -2; while (!feof (ptr_file)) { fscanf (ptr_file, “%d”, &dest[i].id); // UB? fscanf (ptr_file, “%s”, dest[i].name); fscanf (ptr_file, “%d”, &dest[i].gender); i++; if(i==destCapacityMax) return 0; } fclose(ptr_file); return 0; } 这就是我所说的: Student students[5]; deserialize_students(students,5); 另外我有以下问题:我做了什么未定义的行为? 注意: […]

在全局范围内将声明与extern,static和no存储说明符混合使用

我一直在研究何时可以在全局范围内混合使用extern , static和no storage specifier声明的变量。 结果让我很困惑。 这是我发现的(每个段落是一个单独的编译单元): /* ok */ int x; int x; /* ok */ int f(); int f(); /* ok */ int x; extern int x; /* ok */ int f(); extern int f(); /* error: static declaration follows non-static declaration */ int x; static int x; /* ok (no warning) */ […]