C标准保证这size_t是一种可以保存任何数组索引的类型.这意味着,逻辑上,size_t应该能够保存任何指针类型.我在Googles上发现的一些网站上看到这是合法的和/或应该始终有效:
void *v = malloc(10);
size_t s = (size_t) v;
Run Code Online (Sandbox Code Playgroud)
那么在C99中,标准引入了intptr_t和uintptr_t类型,它们是有符号和无符号类型,保证能够保存指针:
uintptr_t p = (size_t) v;
Run Code Online (Sandbox Code Playgroud)
那么使用size_t和有uintptr_t什么区别?两者都是无符号的,并且两者都应该能够保存任何指针类型,因此它们在功能上看起来相同.除了清晰度之外,是否有任何真正令人信服的理由uintptr_t(或者更好的是,a void *)而不是a size_t?在一个不透明的结构中,字段只能由内部函数处理,有没有理由不这样做?
出于同样的原因,ptrdiff_t一直是一个能够保持指针差异的签名类型,因此能够容纳大多数指针,那么它与它intptr_t有何区别?
是不是所有这些类型基本上都服务于同一功能的不同版本?如果没有,为什么?对于其中一个我不能用另一个做什么我不能做什么?如果是这样,为什么C99会在语言中添加两种基本上多余的类型?
我愿意忽略功能指针,因为它们不适用于当前的问题,但随意提及它们,因为我有一种潜在的怀疑,它们将成为"正确"答案的核心.
我有一个用于在C中实现的编程语言的VM.它支持在32位和64位架构以及C和C++下编译.
我正在尝试使用尽可能多的警告来干净地编译它.当我打开时CLANG_WARN_IMPLICIT_SIGN_CONVERSION,我会得到一连串的新警告.
我希望有一个很好的策略,可以使用何时使用int显式无符号类型和/或显式大小的类型.到目前为止,我无法确定该策略应该是什么.
将它们混合使用 - 主要int用于局部变量和参数之类的东西,并在结构中使用较窄的类型- 确实会导致许多隐式转换问题.
我喜欢为struct字段使用更具体的大小类型,因为我喜欢显式控制堆中对象的内存使用量的想法.此外,对于散列表,我在散列时依赖于无符号溢出,因此如果散列表的大小存储为,则很好uint32_t.
但是,如果我尝试在任何地方使用更具体的类型,我发现自己到处都是曲折的迷宫.
其他C项目有什么作用?
C++编程语言中的数组索引的类型是什么?例如在这样的声明中:
int tab[5];
Run Code Online (Sandbox Code Playgroud)
什么类型5被转换?或者它可能只是简单的int?
C标准保证int能够存储每个可能的数组大小.至少,这是我从阅读§6.5.2.1,第1小节(数组下标约束)中理解的内容:
其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应具有整数类型,结果具有类型''type''.
既然我们将ints用作数组下标,为什么我们应该用它size_t来确定数组的大小?
为什么strlen()回报size_t什么时候int就够了?
我最近了解到,引入size_t是为了帮助面向未来的代码,防止本机位数增加和可用内存增加.具体的使用定义似乎是存储某些东西的大小,通常是一个数组.
我现在必须想知道这种未来的证明应该走多远.当迭代数组的下一个任务使用一个unsigned intas作为索引数组时,使用面向未来并且大小适当的size_t定义数组长度毫无意义:
void (double* vector, size_t vectorLength) {
for (unsigned int i = 0; i < vectorLength; i++) {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
事实上,在这种情况下,我可能希望语法严格地将unsigned int上变换为关系运算符的size_t.
这是否意味着迭代器变量i应该只是一个size_t?
这是否意味着任何程序中的任何整数必须在功能上确定是否它将被用作数组索引?
它意味着使用编程开发索引然后应该创建size_t类型的一个新的结果值,特别是如果逻辑依赖于潜在符号的整数值逻辑的任何代码?即
double foo[100];
//...
int a = 4;
int b = -10;
int c = 50;
int index = a + b + c;
double d = foo[(size_t)index];
Run Code Online (Sandbox Code Playgroud)
当然,由于我的代码逻辑创建了一个固定的边界,因此向上转换为size_t不会提供额外的保护.
C#中的数组索引的类型是什么?
例如,在下面的代码中,索引是否会在访问数组元素(第三行)之前转换为int?
T[] myArray = new T[255];
byte index = 2;
T element = myArray[index];
Run Code Online (Sandbox Code Playgroud)
如果不是,使用'byte'类型的索引而不是'int'类型的索引访问数组元素会更快吗?
谢谢
avr-gcc为一个8位微控制器编译一些测试代码
const uint32_t N = 65537;
uint8_t values[N];
Run Code Online (Sandbox Code Playgroud)
我得到了以下编译警告(默认情况下应该是一个错误,真的)
warning: conversion from 'long unsigned int' to 'unsigned int' changes value from '65537' to '1' [-Woverflow]
uint8_t values[N];
Run Code Online (Sandbox Code Playgroud)
请注意,编译此目标时,sizeof(int)为2.
所以看来,在一个数组大小不能超过一个unsigned int.
我对么?这是GCC特定的还是某些C或C++标准的一部分?
在有人评论说8位微控制器通常没有足够的内存来容纳如此大的阵列之前,让我只是期待说这不是重点.
关于这个主题已经有一些问题(1、2、3 )。问题是,似乎没有一个明确的答案。有些答案建议( 1 , 2 ),有些答案建议( 1 , 2 )。其他选项包括、、或使用容器或成员类型。size_tptrdiff_tintuint32_tautodecltype.size()size_type
这个问题似乎不适合基于观点,但我认为事实并非如此。仅仅因为尚未就使用哪种类型达成共识,并不意味着不存在客观的答案。这是因为不同的选择不仅美观,而且实际上可以影响代码的行为。
例如,在循环条件中使用符号不匹配的索引变量类型将导致编译器警告,如下所示。此外,使用范围太小的类型可能会导致溢出,在有符号类型的情况下会导致 UB。同时,在某些情况下改变循环计数器类型可能会导致“疯狂的性能偏差”。
我还想找出最流行的(尽管不一定是最好的)创建 for 循环的方法,因此我使用 GitHub *搜索来查找。结果如下:
| 循环型 | GitHub 上的代码结果计数(平均值;“手动”循环 + 基于范围) |
|---|---|
for (int |
15.8m |
for (size_t |
11.6m |
for (auto |
7.5m |
for (uint32_t |
2.3m |
std::for_each |
501k |
for (ptrdiff_t |
98.7k |
for (decltype |
77.5k |
不同循环类型之间的出现次数肯定存在很大差异,但是,似乎没有明显的杰出领导者。
因此,我发布这个问题询问,在 C++ 的 for 循环中索引变量使用的最佳类型是什么,或者应该选择这种类型的规则或条件是什么?
*:GitHub 搜索工具每次都会为“代码结果”(计数)生成不同的结果,因此我对 26 个值进行了平均。由于搜索是基于文本的,因此它包括表单for (int i = 0; i < n; ++i)和的结果for …
我正在使用下面的简单交换排序算法在Windows中的Visual Studio项目中尝试不同的整数类型.处理器是英特尔.代码是在Release x64中编译的.优化设置为"最大化速度(/ O2)".与编译设置对应的命令行是
/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\SpeedTestForIntegerTypes.pch" /diagnostics:classic
Run Code Online (Sandbox Code Playgroud)
代码本身:
#include <ctime>
#include <vector>
#include <iostream>
void sort(int N, int A[], int WorkArray[]) // exchange sort
{
int i, j, index, val_min;
for (j = 0; j < N; j++)
{
val_min = 500000;
for (i = j; i < N; i++) …Run Code Online (Sandbox Code Playgroud)