我知道浮点数有舍入错误,但我想知道是否存在某些错误不适用的情况,例如乘以零.
对于所有浮点,任何数字的零次是否为零?
这是C11标准的引用:
6.5表达式
......6 访问其存储值的对象的有效类型是对象的声明类型(如果有).如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值.如果使用
memcpy或将值复制到没有声明类型的对象中memmove,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是有效类型复制值的对象,如果有的话.对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型.7对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,- 与对象
的有效类型对应的有符号或无符号类型的类型,
- 类型这是对象的有效类型的限定版本对应的有符号或无符号类型,
- 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员) ,或
- 字符类型.
这是否意味着memcpy不能以这种方式用于打字:
double d = 1234.5678;
uint64_t bits;
memcpy(&bits, &d, sizeof bits);
printf("the representation of %g is %08"PRIX64"\n", d, bits);
Run Code Online (Sandbox Code Playgroud)
为什么它不会给出相同的输出:
union { double d; uint64_t i; } u;
u.d = 1234.5678;
printf("the representation of %g is %08"PRIX64"\n", d, u.i);
Run Code Online (Sandbox Code Playgroud)
如果我使用我的memcpy使用字符类型的版本怎么办:
void *my_memcpy(void *dst, const void *src, size_t n) {
unsigned char …Run Code Online (Sandbox Code Playgroud) 以下代码是否定义良好?
#include <stdio.h>
int ScanFirstOrSecond(const char *s, int *dest) {
return sscanf(s, "%d%d", dest, dest);
}
int main(void) {
int x = 4;
ScanFirstOrSecond("5", &x);
printf("%d\n", x); // prints 5
// Here is the tricky bit
ScanFirstOrSecond("6 7", &x);
printf("%d\n", x); // prints 7
return 0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,这些...论点是否暗示restrict了它们?
我发现最适用的C规范是
fscanf函数依次执行格式的每个指令.......C11dr§7.21.6.24
我正在尝试使用以下公式制作一个宏:(a^2/(a+b))*b,我想确保不会有零除以.
#define SUM_A( x, y ) if( x == 0 || y == 0) { 0 } else { ( ( ( x * x ) / ( ( x ) + ( y ) ) ) * ( y ) )}
Run Code Online (Sandbox Code Playgroud)
然后我调用main里面的宏:
float a = 40, b = 10, result;
result = SUM_A(a, b);
printf("%f", result);
Run Code Online (Sandbox Code Playgroud)
我尝试在if函数周围使用括号,但我在if语句之前一直遇到语法错误.我也尝试过使用return,但我在某处读到你不应该在define中使用它.
位运算符(~,&,|和^)在他们的推动数的按位表示操作.这样的操作会导致不确定的行为吗?
例如,~运算符在C标准中以这种方式定义:
6.5.3.3一元算术运算符
~运算符的结果是其(提升的)操作数的按位补码(也就是说,当且仅当未设置转换的操作数中的相应位时,才会设置结果中的每个位).整数提升在操作数上执行,结果具有提升类型.如果提升的类型是无符号类型,则表达式~E等效于该类型中可表示的最大值减去E.
在所有体系结构上,~0生成一个位模式,其符号位设置为1,所有值位设置为1.在一个补码架构上,该表示对应于负零.这个位模式可以成为陷阱表示吗?
是否存在涉及更常见架构的简单位运算符的未定义行为的其他示例?
我有一个包含整数的字符串,我正在尝试将所有内容放入另一个数组中.当sscanf找不到int我想要循环停止时.所以,我做了以下事情:
int i;
int getout = 0;
for (i = 0; i < bsize && !getout; i++) {
if (!sscanf(startbuffer, "%d", &startarray[i])) {
getout = 1;
}
}
//startbuffer is a string, startarray is an int array.
Run Code Online (Sandbox Code Playgroud)
这导致将所有元素startarray作为第一个char startbuffer.
sscanf工作正常但它不会移动到下一个int它只是停留在第一个位置.
知道什么是错的吗?谢谢.
根据环境和编译器设置,char默认情况下类型可以是有符号或无符号的,这意味着8位2s补码系统上单个字符常量的值范围可以是-128..127或0..255.
在无处不在的ASCII字符集中,其ISO-8859-X扩展或UTF-8编码,大写和小写字母以及数字的值低于127.
但是EBCDIC字符集不是这种情况:
'A'是0xC1,'a'是0x81并且'1'是0xF1.
由于这些值大于127,是否意味着该类型char必须在8位EBCDIC系统上无符号?或者可以'a','A' 并'1'有负值?
其他字符集怎么样?字母或数字可以有负值吗?
最近发现的对 GTA 冗长加载时间的解释(1)表明,许多sscanf()调用strlen()其输入字符串的实现为与其他扫描函数共享的内部例程设置上下文对象 ( scanf(), fscanf()...)。当输入字符串很长时,这可能成为性能瓶颈。解析作为字符串加载的 10MB JSON 文件,sscanf()并通过偏移量和%n转换重复调用被证明是加载时间的主要原因。
我的问题是sscanf()甚至应该读取超出转换完成所需字节的输入字符串吗?例如,以下代码是否会调用未定义的行为:
int test(void) {
char buf[1] = { '1' };
int v;
sscanf(buf, "%1d", &v);
return v;
}
Run Code Online (Sandbox Code Playgroud)
函数应该返回1并且不需要从 中读取多个字节buf,但sscanf()允许从buf第一个字节之外读取?
(1) JdeBP提供的参考资料:
https
: //nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/ https://news.ycombinator.com/ item?id=26297612
https://github.com/biojppm/rapidyaml/issues/40
大多数C程序员都熟悉这个strdup功能.他们中的许多人会认为这是理所当然的,但它不是C标准的一部分(C89,C99和C11都不是).它是POSIX的一部分,可能并非在所有环境中都可用.事实上,微软坚持要重新命名,这_strdup增加了混乱.
用这种方式定义它很容易(在C中):
#include <string.h>
char *strdup(const char *s) {
size_t size = strlen(s) + 1;
char *p = malloc(size);
if (p) {
memcpy(p, s, size);
}
return p;
}
Run Code Online (Sandbox Code Playgroud)
但即使是精明的程序员也很容易弄错.
此外,仅在没有它的系统上重新定义函数证明有点复杂,如下所述:strdup()函数
为什么不在C标准的修订版中包含这些有用的广泛支持的功能?在C99的C标准库中添加了许多新功能,不包括的理由是什么strdup?
我进行了一个简单的实验,比较if-else到只有if(预设默认值).例:
void test0(char c, int *x) {
*x = 0;
if (c == 99) {
*x = 15;
}
}
void test1(char c, int *x) {
if (c == 99) {
*x = 15;
} else {
*x = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
对于上面的函数,我得到了完全相同的汇编代码(使用cmovne).
但是在添加额外变量时:
void test2(char c, int *x, int *y) {
*x = 0;
*y = 0;
if (c == 99) {
*x = 15;
*y = 21;
}
}
void test3(char c, int *x, int *y) …Run Code Online (Sandbox Code Playgroud)