Questions tagged «c»

C是用于系统编程(OS和嵌入式),库,游戏和跨平台的通用编程语言。该标记应与ISO 9899标准(除非另有说明,最新版本9899:2018中定义的有关C语言的一般问题)一起使用-还要使用c89,c99,c11等标记特定于版本的请求。C与C ++截然不同,在没有合理理由的情况下,不应将其与C ++标记结合使用。

4
strcasecmp算法有缺陷吗?
我试图strcasecmp在C中重新实现该功能,并且发现比较过程中似乎存在不一致之处。 从 man strcmp strcmp()函数比较两个字符串s1和s2。不考虑语言环境(有关语言环境的比较,请参阅strcoll(3))。如果分别找到s1小于,匹配或大于s2,则它返回小于,等于或大于零的整数。 从 man strcasecmp strcasecmp()函数对字符串s1和s2进行逐字节比较,而忽略字符的大小写。如果分别找到s1小于,匹配或大于s2,则它返回小于,等于或大于零的整数。 int strcmp(const char *s1, const char *s2); int strcasecmp(const char *s1, const char *s2); 鉴于此信息,我不理解以下代码的结果: #include <stdio.h> #include <string.h> int main() { // ASCII values // 'A' = 65 // '_' = 95 // 'a' = 97 printf("%i\n", strcmp("A", "_")); printf("%i\n", …
34 c  strcmp 

7
指针比较在C中如何工作?比较不指向同一数组的指针是否可以?
在K&R(C编程语言第二版)第5章中,我阅读了以下内容: 首先,可以在某些情况下比较指针。如果p和q指向同一个数组的成员,则关系一样==,!=,<,>=,等正常工作。 这似乎暗示着只能比较指向同一数组的指针。 但是当我尝试这段代码时 char t = 't'; char *pt = &t; char x = 'x'; char *px = &x; printf("%d\n", pt > px); 1 被打印到屏幕上。 首先,我以为我会得到未定义或某种类型或错误的信息,因为pt和px没有指向同一数组(至少在我看来)。 同样是pt > px因为两个指针都指向存储在堆栈中的变量,并且堆栈变小,所以的内存地址t大于x?的内存地址。这是为什么pt > px呢? 引入malloc时,我会更加困惑。同样,在K&R的8.7章中,内容如下: 但是,仍然有一个假设,即sbrk可以有意义地比较指向返回的不同块的指针。该标准不能保证这一点,该标准仅允许在数组内进行指针比较。因此,此版本malloc仅可在通用指针比较有意义的机器之间移植。 将指向堆上分配的空间的指针与指向堆栈变量的指针进行比较,我没有任何问题。 例如,以下代码可以很好地工作并1可以打印: char t = 't'; char *pt = &t; char *px = malloc(10); strcpy(px, pt); …

4
调用fork时是否复制线程?
如果我有一个运行线程的程序并fork()在基于UNIX的系统上调用,是否复制了线程?我知道当前进程的虚拟内存将1:1复制到新进程。我知道线程在进程的虚拟内存中有自己的堆栈。因此,至少也应该复制线程堆栈。但是,我不知道线程中是否还有其他不驻留在虚拟内存中并且因此不会被复制的线程。如果没有,这两个进程是共享线程还是它们是独立副本?

6
将2个字节转换为带符号的16位整数的正确方法是什么?
在这个答案中,zwol宣称: 从外部源将两个字节的数据转换为16位带符号整数的正确方法是使用如下辅助函数: #include <stdint.h> int16_t be16_to_cpu_signed(const uint8_t data[static 2]) { uint32_t val = (((uint32_t)data[0]) << 8) | (((uint32_t)data[1]) << 0); return ((int32_t) val) - 0x10000u; } int16_t le16_to_cpu_signed(const uint8_t data[static 2]) { uint32_t val = (((uint32_t)data[0]) << 0) | (((uint32_t)data[1]) << 8); return ((int32_t) val) - 0x10000u; } 上面的哪个函数合适,取决于数组包含小端还是大端表示。字节序不是这里要讨论的问题,我想知道为什么zwol0x10000u从uint32_t转换为的值中减去int32_t。 为什么这是正确的方法? …

1
为什么连续写入会在缓冲区中保留4K字节?
我基本上有以下代码: int fileWrite(int file, void * pBuffer, size_t size) { size_t bytesWritten = (size_t)write( file, pBuffer, size ) ; if (bytesWritten != size) { return -1; } return 0; } 如果大小为1GB,则可以使用,但是当大小为〜2GB时,则可以连续保留4K字节。我可以通过将写操作包装在循环中并向上移动缓冲区来解决此问题,但是我很好奇为什么它总是失败。 例如,如果大小为2147483648,则只写2147479552,而使4096不写。为什么会发生这种情况,并且总是将写操作包装在循环中是否正确?
30 c  linux  system-calls 

4
用C和C ++调用的(…)是什么?
的用途之一...是表示可变参数 C和C ++中的实体。 它叫什么名字? 以这种方式使用时,它被归类为运算符还是其他? 还有其他细节...吗? 编辑: 我知道的目的...。我在问它的​​名称和分类,我希望它在C和C ++中都相似。

2
为什么C的BNF语法允许使用init-declarator的空序列进行声明?
当查看C的BNF语法时,我认为声明的生产规则看起来像这样很奇怪(根据https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C%20in%20Backus-Naur%20form.htm): <declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ; 为什么要*为此使用量词(表示零次或多次出现)init-declarator?这允许诸如int;或之类的语句void;在语法上有效,即使它们在语义上无效。他们难道不是在生产规则中使用了+量词(一次或多次)*吗? 我尝试编译一个简单的程序,以查看编译器的输出,它所做的只是发出警告。 输入: int main(void) { int; } 输出: test.c: In function ‘main’: test.c:2:5: warning: useless type name in empty declaration int; ^~~

2
混淆二维数组时strlen的意外优化
这是我的代码: #include <string.h> #include <stdio.h> typedef char BUF[8]; typedef struct { BUF b[23]; } S; S s; int main() { int n; memcpy(&s, "1234567812345678", 17); n = strlen((char *)&s.b) / sizeof(BUF); printf("%d\n", n); n = strlen((char *)&s) / sizeof(BUF); printf("%d\n", n); } 使用gcc 8.3.0或8.2.1以及任何优化级别,但我期望的是-O0此输出。编译器决定将限制于,因此永远不能等于或超过被除以的值。0 22 2strlenb[0] 这是我的代码中的错误还是编译器中的错误? 标准中并未明确阐明这一点,但是我认为指针来源的主流解释是,对于任何对象X,代码(char *)&X都应生成一个可以迭代整个对象的指针X-即使X碰巧具有子数组作为内部结构。 (奖金问题,是否有gcc标志来关闭此特定优化?)


3
C是否与C ++具有等效的std :: less?
我最近在回答一个关于p < q当p和q是指向不同对象/数组的指针时在C 中执行的未定义行为的问题。这让我想到:C ++ <在这种情况下具有相同(未定义)的行为,但是还提供了标准库模板std::less,该模板保证可以返回与<可以比较指针时相同的东西,并在不能比较时返回一些一致的顺序。 C是否提供具有类似功能的东西,从而可以安全地比较任意指针(相同类型)?我尝试浏览C11标准并没有发现任何东西,但是我在C中的经验比在C ++中小得多,因此我很容易错过一些东西。

1
C语言中重叠对象的语义是什么?
考虑以下结构: struct s { int a, b; }; 通常为1,此结构的大小为8,对齐方式为4。 如果我们创建两个struct s对象(更准确地说,我们将两个这样的对象写入分配的存储区),而第二个对象与第一个对象重叠怎么办? char *storage = malloc(3 * sizeof(struct s)); struct s *o1 = (struct s *)storage; // offset 0 struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4 // now, o2 points half way into o1 *o1 …

5
按位运算会导致意外的可变大小
语境 我们正在移植最初使用PIC单片机的8位C编译器编译的C代码。为了防止无符号全局变量(例如,错误计数器)回滚到零,使用了一个常见的习惯用法: if(~counter) counter++; 此处的按位运算符将所有位取反,并且仅当counter小于最大值时该语句才为真。重要的是,无论变量大小如何,此方法均有效。 问题 我们现在的目标是使用GCC的32位ARM处理器。我们注意到,相同的代码会产生不同的结果。据我们所知,按位补码运算返回的值与我们期望的大小不同。为了重现这一点,我们在GCC中进行编译: uint8_t i = 0; int sz; sz = sizeof(i); printf("Size of variable: %d\n", sz); // Size of variable: 1 sz = sizeof(~i); printf("Size of result: %d\n", sz); // Size of result: 4 在输出的第一行中,我们得到的是:i1个字节。但是,的按位补码i实际上是四个字节,这会引起问题,因为与此进行比较现在无法给出预期的结果。例如,如果这样做(在哪里i是正确初始化的uint8_t): if(~i) i++; 我们将看到i从0xFF到0x00的“环绕”。与以前的编译器和8位PIC微控制器中预期的运行方式相比,GCC的行为有所不同。 我们知道我们可以通过如下方式解决此问题: if((uint8_t)~i) i++; 或者,通过 if(i < 0xFF) …

2
可比性测试比%运算符更快?
我注意到计算机上有一件奇怪的事情。*手写除数测试比%操作员快得多。考虑最小的示例: * AMD锐龙Threadripper 2990WX,GCC 9.2.0 static int divisible_ui_p(unsigned int m, unsigned int a) { if (m <= a) { if (m == a) { return 1; } return 0; } m += a; m >>= __builtin_ctz(m); return divisible_ui_p(m, a); } 该示例受奇数a和限制m > 0。但是,可以很容易地将其推广到所有a和m。该代码只是将除法转换为一系列的加法。 现在考虑使用以下命令编译的测试程序-std=c99 -march=native -O3: for (unsigned int a …

1
gcc-10.0.1特定段错误
我有一个带有C编译代码的R软件包,该软件包相当稳定了一段时间,并且经常针对各种平台和编译器(windows / osx / debian / fedora gcc / clang)进行测试。 最近,添加了一个新平台来再次测试该软件包: Logs from checks with gcc trunk aka 10.0.1 compiled from source on Fedora 30. (For some archived packages, 10.0.0.) x86_64 Fedora 30 Linux FFLAGS="-g -O2 -mtune=native -Wall -fallow-argument-mismatch" CFLAGS="-g -O2 -Wall -pedantic -mtune=native -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong -fstack-clash-protection -fcf-protection" …

4
为什么C中的绝对值函数不接受const输入?
在C语言中,绝对值函数(接受浮点数)的原型为 float fabsf( float ); 为什么这个原型不接受一个常量值,像这样: float fabsf( float const ); fabsf不会更改输入的值,对吗? 如果我有一个接受输入并调用fabsf的函数,我是否被迫避免将输入指定为const? 在这种情况下,处理const正确性的适当方法是什么?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.