Tag: c99

如何在大多数平台上使用C99标准类型以实现最大的可移植性和效率?

首先,这是我理解并思考问题的真实情况。 对单个变量(如计数器或循环索引)使用快速数据类型。 例如: #define LOOP_COUNT (100U) uint_fast8_t index; for(index = 0; index < LOOP_COUNT; index++){ /* Do something */ } 我想这里最合适的类型是uint_fast8_t因为index永远不会超过255,这将是所有平台上最快的实现。 如果我使用unsigned int代替它,它将在> = 16位平台中最快,但在<16位平台中将更慢,因为int是标准的最小16位。 此外,如果我使用uint8_t ,它将在> 8位平台上变慢,因为编译器添加AND 0xFF指令来检查每个增量的溢出(我的ARM7编译器甚至在全速优化时也这样做)。 size_t也不是一个选项,因为它可能大于本机整数大小。 如果预计8位溢出,那么这边是坏的(?),它就不会发生。 程序员应该手动检查溢出(因为他/她应该恕我直言),这可能会导致错误的代码,如果忘记。 此外,如果LOOP_COUNT在8位平台上“意外”设置为大于255的值,编译器(甚至PC-Lint让我惊讶)也不会发出任何警告/问题,但警告将在8位平台上生成,这将降低可移植性并引入错误,但这可以通过#if检查来避免。 如果像数组或结构中那样关注内存使用情况,请尽可能使用最少的数据类型。 例如: uint_least8_t array[100]; 如果关注内存使用情况,它是最便携,最有效的声明数组的方法。 如果平台上可以进行字节访问,则此类型将提供字节数组,否则将提供最小的可访问宽度整数数组。 此外,如果我们有结构数组,则可以在结构中使用最少类型。 最小类型也可能遇到快速类型的问题,因为对于这两种情况,可以在不同平台上改变变量的宽度。 尽可能避免使用固定宽度的数据类型,因为在某些平台上它们甚至可能不存在,除了硬件寄存器访问,通信协议映射等,我们需要知道变量的确切位。 例如: typedef struct { uint8_t flags; uint8_t length; uint8_t data[100]; uint16_t crc; } […]

哪些C99function被视为有害或不受支持

我通常在C89中编写C代码,现在C99的一些function(如intxx_t或__VA_ARGS__或snprintf )非常有用,甚至可能至关重要。 在我更多地从C89到C99的要求之前,我想知道哪些C99function得到了广泛支持,哪些function得不到广泛支持甚至被认为是有害的。 我知道我们可以检查我们的目标编译器支持,但这会缩小我们的支持范围,因为这是开源软件,我更希望得到更广泛的支持。 例如,我们使用Solaris(suncc)编译器和gcc,但是我们可能会有其他编译器移动,而我们可以通过很少的努力保持兼容性。 例如,我从未在Windows上工作,也不了解Windows编译器,但保持Windows兼容性会很好。

如何在gcc中强制执行C89样式的变量声明?

我在代码库上工作,主要是带有一点点C ++的C语言,并且主要是用gcc构建的,但偶尔需要用MSVC构建。 微软的C编译器仍然是C89,只有一些小的扩展,它仍然不支持C ++ / C99的混合代码和变量定义。 因此,我需要找到一种方法来防止开发人员在使用gcc时编写无序代码/变量定义,否则构建随后会破坏MSVC。 如果我使用gcc -std=c89那么一切都会中断,因为不允许使用C ++风格的注释(可能还有其他问题,但我还没有进一步研究过)。 如果我使用gcc -std=gnu89则允许无序代码/变量定义,这对我也没有帮助。 有任何想法吗 ? 我想我只需要像gcc -std=c99 -fno-inline-variable-definitions这样的选项,如果存在这样的选项的话。

使用C中的预取和缓存优化对arrays的线性访问

披露:我在programmers.stack上尝试过类似的问题,但那个地方离活动堆栈还差不多。 介绍 我倾向于使用大量的大图像。 它们也有多个序列,必须重复处理和播放。 有时候我使用GPU,有时候是CPU,有时候都是。 大多数访问模式本质上是线性的(来回),让我思考有关数组的更基本的事情,以及如何编写代码优化以在给定硬件上实现最大内存带宽(允许计算不阻塞读/写) 。 测试规格 我在2011年MacbookAir4,2(I5-2557M)上使用4GB RAM和SSD完成了这项工作。 除了iterm2之外,在测试期间没有其他任何东西在运行。 gcc 5.2.0(自制)带标志: -pedantic -std=c99 -Wall -Werror -Wextra -Wno-unused -O0带有额外的include和库标志以及框架标志,以便使用我倾向于使用的glfw计时器。 我可以在没有的情况下完成它,没关系。 当然,所有64位。 我已经尝试使用可选的-fprefetch-loop-arrays标志进行测试,但它似乎根本没有影响结果 测试 在堆上分配两个n bytes数组 – 其中n是8, 16, 32, 64, 128, 256, 512 and 1024 MB 一次将array初始化为0xff ,字节 测试1 – 线性拷贝 线性副本: for(uint64_t i = 0; i < ARRAY_NUM; ++i) { array_copy[i] = array[i]; […]

无符号和较大签名类型之间隐式转换的不一致行为

请考虑以下示例: #include int main(void) { unsigned char a = 15; /* one byte */ unsigned short b = 15; /* two bytes */ unsigned int c = 15; /* four bytes */ long x = -a; /* eight bytes */ printf(“%ld\n”, x); x = -b; printf(“%ld\n”, x); x = -c; printf(“%ld\n”, x); return 0; } […]

使用联合在具有共同初始序列的两个结构之间进行转换是否合法且定义良好的行为(参见示例)?

我有一个公开面向结构A和内部结构B的API,需要能够将结构B转换为结构A.以下代码在C99(和VS 2010 / C89)和C中是合法且定义良好的行为 ++ 03 / C ++ 11? 如果是,请解释是什么使它明确定义。 如果不是,那么在两种结构之间进行转换的最有效和跨平台的方法是什么? struct A { uint32_t x; uint32_t y; uint32_t z; }; struct B { uint32_t x; uint32_t y; uint32_t z; uint64_t c; }; union U { struct A a; struct B b; }; int main(int argc, char* argv[]) { U u; ubx = 1; […]

有符号和无符号整数的整数转换等级

例如,如果我有, int a = 42; unsigned b = 10; int c = a + b; 对于这个陈述, int c = a + b; 是第一个转换为unsigned int还是b将转换为signed int ? unsigned int和signed都具有相同的转换级别,那么我们如何知道哪一个将被转换? 有标准规则吗?

如何找到我当前的编译器标准,如果它是C90等

我正在研究Linux机器。 是否有任何系统命令可以找到我正在使用的C编译器后面的标准?

C99的所有function是否也在C ++中?

此页面列出了C99中新增的53个function(即它们是C99但不是C89)。 所有这些function都在C ++中吗? 甚至是C ++ 98? 如果没有,哪些function在C ++中,哪些不是?

人类可以通过限制限定符做出什么?

如果我正确地获得了C99 restrict关键字,那么用它来限定指针是一个承诺,它引用的数据不会在编译器的后面通过别名修改。 相比之下,我理解const限定符的方式是编译器强制执行的文档,即在人类编写代码的背后不会修改给定对象。 编译器可能会得到一个提示作为副作用,但作为程序员我并不在乎。 以类似的方式,将函数原型中的restrict限定符视为要求用户在调用期间确保独占访问(“避免别名”或可能更强的东西)是否合适? 它应该用作“文件”吗? 另外,有一些事情要理解, restrict限定指针而不是它指向的数据(如const那样)? 编辑:我原本认为restrict可能会影响线程代码,但这似乎是错误的,所以我从问题中删除线程的引用,以避免混淆读者。