这段代码有一个有趣的bug:
some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;
for (i = 0;
i < sizeof(struct_array1) / sizeof(struct_array1[0]);
struct_array1[i].value = struct_array2[i++].value = 1)
;
Run Code Online (Sandbox Code Playgroud)
对于大多数编译器,上面的代码导致将相应数组中所有结构的"value"字段设置为1.但是,对于一个特定的编译器(让我们称之为xcc),struct_array1中的结构未正确初始化.对于所有结构,"value"字段设置为0,这让我感到惊讶.
以下代码段在所有编译器上按预期工作:
for (i = 0;
i < sizeof(struct_array1) / sizeof(struct_array1[0]);
i++)
{
struct_array1[i].value = struct_array2[i].value = 1;
}
Run Code Online (Sandbox Code Playgroud)
现在,我完全离开这里,还是有问题的编译器"xcc"只是显示错误?
我在第一个代码片段中找不到任何显示特定于实现的行为的内容; 根据我的理解,后缀增量应该优先于赋值,并且应该从右到左评估赋值.第一个代码片段应该没什么奇怪的,除了它有点不可读.
我可以假设以下不变量吗?
void foo(char *buf, size_t len) {
// "buf" points to either an array or memory allocated with malloc().
assert((uintptr_t)(buf + len) < UINTPTR_MAX);
}
Run Code Online (Sandbox Code Playgroud)
在我正在编写的解析器中,我想使用指针标记某些偏移:例如,我可能有char *end_of_submessage,end_of_submessage相对于我当前的缓冲区.但是如果子消息没有在当前缓冲区内结束,我想使用一个大于当前缓冲区中任何偏移量的值.所以我会这样做:
void parse(char *buf, size_t len, uintptr_t end_of_submessage) {
// Some parsing that might increment "buf"
// ...
// If end_of_submessage == UINTPTR_MAX, processing will not be
// triggered even if we have processed our entire current buffer.
if ((uintptr_t)buf >= end_of_submessage)
process_submsg_end();
}
Run Code Online (Sandbox Code Playgroud)
但是如果malloc()返回内存ptr + len == UINTPTR_MAX …
我刚刚在C99 ISO标准7.19.6.1 The fprintf function第6小节中发现了以下内容,详细说明了转换标志,特别是0标志:
0: d,i,o,u,x,X,a,A,e,E,f,F,g和G转换,前导零(跟随符号或基数的任何指示)用于填充场宽度而不是执行空间填充,除非转换无穷大或NaN.
到目前为止,我知道以下几行将产生显示的输出:
printf ("%5d\n", 7); // produces " 7"
printf ("%05d\n",7); // produces "00007"
Run Code Online (Sandbox Code Playgroud)
但是,在第8小节详细说明了转换修饰符,我看到:
d,i: int参数在样式[ - ] dddd中转换为带符号的十进制数.精度指定要显示的最小位数; 如果转换的值可以用更少的数字表示,则使用前导零进行扩展.
显然不是这种情况,因为默认行为是填充空格而不是零.或者我在这里误读了什么?
当我有一个像这样的循环:
for (int i = 0; i < SlowVariable; i++)
{
//
}
Run Code Online (Sandbox Code Playgroud)
我知道在VB6中,SlowVariable每次迭代循环都会访问它,使得以下内容更有效:
int cnt = SlowVariable;
for (int i = 0; i < cnt; i++)
{
//
}
Run Code Online (Sandbox Code Playgroud)
我是否需要在GCC中进行相同的优化?或者它只评估SlowVariable一次?
我希望我的程序能够在没有警告的情况下使用clang进行编译.该功能似乎在编译时有效但为什么?我该如何处理警告?
$ clang cpu-disk-info.c
cpu-disk-info.c:108:17: warning: implicit declaration of function 'read' is
invalid in C99 [-Wimplicit-function-declaration]
while ((n = read(0, buf, betterSIZE)) > 0)
^
cpu-disk-info.c:109:5: warning: implicit declaration of function 'write' is
invalid in C99 [-Wimplicit-function-declaration]
write(1, buf, n);
^
Run Code Online (Sandbox Code Playgroud)
码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 1024
#define betterSIZE 4*SIZE /* read a better size at a time */
int main(int argc, char **argv)
{
/* copy(); */
/* make the names known */
void info(char …Run Code Online (Sandbox Code Playgroud) 例如,具有C99标准的C编程语言支持十六进制浮点文字,但C++与C++ 03标准不支持.
我对它进行了测试,GCC在C++ 03模式下识别了十六进制浮动文字(-std = c ++ 03),但根据C++标准,它不应该.我知道,这不是一个悲剧,我只是对这个问题感兴趣..
GCC编制器是否符合标准?你能推荐我一个符合标准"完美"的C/C++编译器吗?
假设一个纯粹的非优化编译器,在初始化变量并在声明后为其赋值时,机器代码是否存在差异?
初始化方法:
int x = 2;
Run Code Online (Sandbox Code Playgroud)
作业方式:
int x;
x = 2;
Run Code Online (Sandbox Code Playgroud)
我使用GCC输出为这两种不同方法生成的程序集,并且两者都产生了一条机器指令:
movl $2, 12(%esp)
Run Code Online (Sandbox Code Playgroud)
该指令只是将x变量保存的内存设置为值2.GCC可能会对此进行优化,因为它可以识别操作的最终结果; 但我认为这是解释这两个版本的唯一方法.我的理由是两个版本都做同样的事情:将内存的一部分设置为特定值.
那么,如果生成的机器代码相同,那么为什么通常会在术语" 初始化 "和" 赋值 " 之间进行区分?
术语" 初始化 " 是否纯粹用于区分具有特定值的变量,这些变量具有在内存中留下任何垃圾值的那些(非初始化)变量?
我正在查看C99规范(N1256.pdf),其中说(第11506页):
const int *ptr_to_constant;
int *const constant_ptr;
Run Code Online (Sandbox Code Playgroud)
"ptr_to_constant指向的任何对象的内容不应该通过该指针修改,但是ptr_to_constant本身可以更改为指向另一个对象.同样,constant_ptr指向的int的内容可能会被修改,但是constant_ptr本身应该总是指向同一地点." (6.7.5.1指针声明符)
从我之前读到的内容来看,以下两个陈述产生了相同的行为.
int *const constant_ptr; /* This form is mentioned in the standard */
int const *constant_ptr; /* This form is NOT mentioned in the standard */
Run Code Online (Sandbox Code Playgroud)
我想知道第二种形式是正确的还是只是一种延伸.
在此先感谢,-S
C99指定初始化器或各种CGSizeMake,CZRectMake等宏是否更像现代Objective-C中的惯例?
它几乎看起来像个人风格偏好,但我看到的C99风格的一个优点是价值的意图是清晰明确的.
CGRect rect = CGRectMake(x, y, width, height)
Run Code Online (Sandbox Code Playgroud)
如果你混淆了价值的顺序,会给你带来心痛,如:
CGRect rect = (CGRect){.origin.x = x, .origin.y = y, .size.width = width, .size.height = height};
Run Code Online (Sandbox Code Playgroud)
毫无疑问,高度正在获得你给予它的价值.人们继续使用现有宏的原因是什么?
"可可编码公约"的文档中没有任何关于此的内容和我遇到的风格指南之一,它是GitHub风格指南:https://github.com/github/objective-c-conventions
我已经看到了在C99中使用以下表达式分配2D数组的各种建议:
int (*array)[cols] = malloc(rows * sizeof *array);
Run Code Online (Sandbox Code Playgroud)
我想知道三件事:
整个结构是否在堆上分配?或者这实际上是一堆指针(在堆栈上)指向堆上的数组..?
分配的内存是否完全连续?
是否只需要一次调用free(array)来释放整个2D结构?我在某个地方读过这个 - 不记得在哪里 - 它似乎对我有用,但我想明白为什么.