即使在脚本中,开发人员也保证变量永远不会超过一个字节,有时甚至超过两个字节,这是很常见的.许多人决定使用int每种可能变量的类型来表示0-1范围内的数字.
为什么使用char或short反而伤害这么多?
我想我听到有人说int是"更标准"类型的..类型.这是什么意思.我的问题是数据类型int是否具有任何明确的优势short(或其他较小的数据类型),因为人们过去几乎总是诉诸于哪些优势int?
我只是注意到我可以使用\将单行注释扩展到下一行,类似于在预处理器指令中这样做.
为什么没有人说这种语言功能?我甚至没有在书中看到它..什么语言版本支持这个?
我的项目需要完全了解sizeof操作员的工作原理。C 标准规范在这方面是模糊的,依赖我对它的解释是危险的。我特别感兴趣的是何时以及如何sizeof处理这些数据。
我之前的知识表明它是一个编译时运算符,我从未质疑过这一点,因为我从未滥用sizeof太多。
然而:
int size = 0;
scanf("%i", &size);
printf("%i\n", sizeof(int[size]));
Run Code Online (Sandbox Code Playgroud)
例如,这不能在编译时以任何意义进行评估。
char c = '\0';
char*p = &c;
printf("%i\n", sizeof(*p));
Run Code Online (Sandbox Code Playgroud)
我不记得生成 U/B 的确切代码,但这里*p是一个实际的表达式(RTL 一元解引用)。通过假设,这是否意味着这sizeof(c+c)是一种通过表达式强制编译时评估的方法,或者是否会被编译器优化?
是否sizeof返回 type 的值int,是size_t(我的平台上的 ULL),还是实现定义的?
本文指出“操作数sizeof不能是类型转换”,这是不正确的。类型转换与sizeof运算符具有相同的优先级,这意味着在同时使用两者的情况下,它们只是从右到左进行计算。sizeof(int) * p可能不起作用,因为如果操作数是大括号中的类型,则首先处理它,但sizeof((int)*p)工作得很好。
我要求对如何sizeof实施进行一些技术说明。这对于那些不想传播错误信息、不准确信息或像我一样不想从事直接依赖于它的项目的人来说是有用的。
这是有问题的构造:
int main (void)
{
int a = 5;
(func)(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用 GNU GCC C99 编译会发生以下情况:
func被定义为一个函数,那么main()该函数就会被执行。func之前未定义为函数main但是,如果我删除func函数周围的大括号,函数将被隐式声明,因此即使它是在另一个翻译单元中定义的,它也会执行,这是我一直期望的行为。
递归下降解析器通过函数调用表达式的存在来识别函数调用表达式(也根据标准),这(arguments)就是为什么像这样的代码3(a);会发出错误:“被调用的对象不是函数或函数指针”。就像其他类似的操作(例如后缀增量)一样,前面的内容(arguments)预计是一个子表达式 - 在这种情况下,约束需要一个函数或函数指针的操作数。对于所有其他操作,您可以随意添加任意数量的括号:((a))++这不会改变任何事情,但是对于函数调用,它看起来并不完全像那样。
为什么该代码的行为会有所不同,这是我不知道的语言功能,还是一些精心设计的解析设计选择的结果?
int arr[] = { 0, 1, 2, 3, 4, 5 };
Run Code Online (Sandbox Code Playgroud)
我正在执行地址操作测试,以增加我对ref和deref的理解.这里有很多困惑.
我发现&*(arr+4)使用相同的地址,&arr[4]但我从未见过这样的任务&*
另外我认为*(&arr+4)使用相同的地址,&arr+4但它对我没有任何意义.
我找不到相关的信息,所以我会问这里,为什么*(&arr+4)使用相同的地址&arr+4,为什么*(&arr+4)不同&arr[4]呢?
我没有发现任何特别适合这个目的。
我试图找出一个函数来计算字符串中每个字符的出现次数,以便我可以在最后从长度中取出它们以找出该字符串中使用了多少同质字符。
我试过嵌套循环,第一个应用,第二个扫描字符串并有条件地满足字符,如果它没有出现在字符串的其他地方:
size_t CountUniqueCharacters(char *str)
{
int i,j;
char unique[CHAR_MAX];
for(i=strlen(str); i>=0; i--)
{
for(j=strlen(str); j>=0; j--)
{
if(str[i] != unique[j])
unique[j] = str[i];
}
}
return strlen(unique);
}
Run Code Online (Sandbox Code Playgroud)
这并不奏效。
如果您愿意限制某人键入诸如"aaaaaaaaaaaaa".
好吧,我以为我知道关于指针和内存操作的一切,但有一点让我好奇.strcmp到目前为止,我一直在比较字符串,但..
这个表达是正确的:
#include <stdio.h>
int main()
{
char* str1 = "I love StackOverflow"; // dram memory alocated
char* str2 = "I love StackOverflow";
if(str1 == str2) printf("%s and %s are equal", str1, str2);
else printf("%s and %s are not equal", str1, str2);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
哪个应该在str1和str2的每个内存块之间进行比较?在这种情况下..如果我们使用:
char str1[] = "I love StackOverflow"; // saving them on stack
char str2[] = "I love StackOverflow";
Run Code Online (Sandbox Code Playgroud)
相反,它不会输出它们是相等的.为什么?
我使用C :: B在Win7的MinGW的gcc上编译了以下测试代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Func. prototype */
char* returnString (void *str);
int main()
{
printf("%s", returnString("Hello World!!!!!!!!!!!!"));
return 1;
}
char* returnString (void *str)
{
char *local = malloc(strlen((char*)str));
strcpy(local, (char*)str);
return local;
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,分配会导致泄漏/ u/b ..因为我必须分配+1空终结符所在的一个空闲字节.但它不是导致泄漏或崩溃,而是像null终止一样工作.有什么方法可以解决这个问题吗?..而不是通过5543行代码+1使用.
在语法上它是有道理的(虽然它看起来像其他语言,我不是特别喜欢),它可以节省大量的打字和代码空间,但它有多糟糕?
if(p1 + (unsigned)p2 + (unsigned)p3 == NULL)
{
// all pointers are NULL, exit
}
Run Code Online (Sandbox Code Playgroud)
使用带有指针右值的指针算法,我看不出它是如何给出一个错误的结果(即使并非所有指针都是NULL,整个表达式也要求为NULL),但我不知道这可能会隐藏多少邪恶这样做是不是很糟糕,不常见的方法是检查是否有大量指针都是NULL?
我们得到了如下的2D分配:
char** arr;
short i = 0;
arr = malloc(sizeof(char*)*10);
for( ; i<10; i++)
{
arr[i] = malloc(sizeof(char)*100);
}
Run Code Online (Sandbox Code Playgroud)
分配arr[10][100];
然后我们需要像这样释放它:
for(i=0; i<sizeof(arr); i++) free(arr[i]);
free(arr);
Run Code Online (Sandbox Code Playgroud)
所以我想创造一个节省时间,空间和混乱的功能,我有这个:
void pfree(void** data)
{
int i;
for(i=0; i<sizeof(data); i++)
{
free(data[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
功能是相关的,如果没有另外的方法吗?
我正在编写自己的基于 GCC 的 C 预处理器。到目前为止,它几乎是相同的,但我认为多余的是对由 virue of 连接的令牌执行任何形式的检查##。所以在我的预处理器手册中,我写了这个:
3.5 串联
...
GCC 禁止连接两个互不兼容的预处理标记,例如“x”和“+”(以任何顺序)。这将导致以下错误:“粘贴“x”和“+”没有给出有效的预处理标记”但是对于这个预处理器来说这不是真的- 连接可能发生在任何标记之间。
我的推理很简单,如果它扩展为无效代码,那么编译器将产生错误,因此我不必显式处理此类情况,从而使预处理器变慢并增加代码复杂性。如果它产生了一个有效的代码,那么这个限制移除只会使它更灵活(尽管可能在极少数情况下)。
所以我想问一下,为什么这个错误真的发生了,为什么这个限制实际上被应用了,如果我在我的预处理器中忽略它是一种真正的犯罪吗?
int main (void)\n{\n auto int func (int a);\n int func (int a); // <-- concerned line\n}\nRun Code Online (Sandbox Code Playgroud)\n我正在研究静态分析仪,或者可以这么说。我必须了解编译器这样做的根本原因。
\n为什么 GCC 会出现以下错误:
\n\n\n错误:\xe2\x80\x98func\xe2\x80\x99 的非静态声明遵循静态声明
\n
是什么使得auto int func (int a);“静态声明”?
考虑我设法编写的以下代码:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
0123456789
如果我这样做,FOR(i=5, i<10, i)
那么输出分别是56789
我的问题是合法的吗?它会在不同的情况下导致任何错误吗?它是否像for循环一样工作?