这段代码的行为是否定义得很好?
#include <stdio.h>
#include <stdint.h>
int main(void)
{
void *ptr = (char *)0x01;
size_t val;
ptr = (char *)ptr + 1;
val = (size_t)(uintptr_t)ptr;
printf("%zu\n", val);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的意思是,我们可以为指针分配一些固定数字,即使它指向某个随机地址也会增加它吗?(我知道你不能取消引用它)
我有很多用C++编写的库.我想从C#调用这些库,但是,我遇到了很多问题.我想知道是否有书或指南告诉我该怎么做.
我曾经使用 VSCode C/C++扩展。这个扩展中有一个功能(在 json 文件中),称为“includePath”,我可以设置标头的路径,因此无需执行 CMake 或 make,我就会从这些中获得标头和代码完成的建议。
现在我已经切换到 neovim 和 clangd 作为代码完成的语言服务器。我进行了大量搜索以在 clangd options 中找到相应的功能,但除了此链接之外我找不到任何其他内容。
既然clangd是一个强大的语言服务器,我想知道它是否没有这样的功能。所以我想知道clangd中是否真的有这样的功能?如果是的话我该如何使用它?
注意:我使用一个名为“coc-clangd”的语言客户端。我不知道这是否重要。
用gcc -std=c99 -Wextra
这段代码编译:
#include <stdio.h>
struct T {
int a;
int *b;
int c;
};
int main(void)
{
struct T t = {.b = ((int []){1, 1})};
printf("%d\n", t.b[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给我一个警告:
demo.c:11:12: warning: missing initializer for field ‘c’ of ‘struct T’ [-Wmissing-field-initializers]
struct T t = {.b = ((int []){1, 1})};
^
demo.c:6:9: note: ‘c’ declared here
int c;
^
Run Code Online (Sandbox Code Playgroud)
但是指定的初始值设定项应该初始化为其余成员的零,即使它们被省略.
为什么警告?(clang
编译同一段代码而不发出警告)
gcc version 6.3.0 20170516 (Debian 6.3.0-18)
clang version 3.8.1-24 (tags/RELEASE_381/final)
Run Code Online (Sandbox Code Playgroud) 我们可以使用预处理器来知道是否unsigned long long
定义了:
#include <limits.h>
#ifndef ULLONG_MAX
typedef unsigned long t_mask;
#else
typedef unsigned long long t_mask;
#endif
Run Code Online (Sandbox Code Playgroud)
但是如何知道如何__uint128_t
定义?
struct A{
int a; int b;
};
static const struct A a = {.a1 = 1, .a2 = 42};
struct B{
struct A[666][510]
};
static const struct B b;
Run Code Online (Sandbox Code Playgroud)
我想b
用a的副本初始化.但是,我不能碰static const
的东西memcpy()
.我需要b
做到static const
这一点,因为这样它就会被闪存而不是内存.
我该如何做这项工作.我认为编译器正在arm-none-eabi-gcc
使用-std=c89
.
您可能知道,VLA 有优点也有缺点,并且在 C11 中它们是可选的。
我认为使 VLA 成为可选的主要原因是:“堆栈可能会爆炸”:
int arr[n]; /* where n = 1024 * 1024 * 1024 */
Run Code Online (Sandbox Code Playgroud)
但是指向 VLA 的指针又如何呢?
int m, n;
scanf("%d %d", &m, &n);
int (*ptr)[n] = malloc(sizeof(int [m][n]));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不存在炸毁堆栈的风险,而且在我看来它们非常有用。
我的问题是:
委员会是否可以保留指向 VLA 的指针,从而使指向非指针类型的 VLA 成为可选?
或者一件事暗示另一件事?
(原谅我糟糕的英语)
在网上搜索了一下后,我得出的结论是,指定的初始值设定项不是任何C++标准的一部分,但是在使用g ++编译这段代码时(4.7.0)
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int test[2][2] ={
[0]={1,2},
[1]={3,4},
};
for (int x = 0; x<2;x++)
{
for (int y = 0; y<2; y++)
{
cout << test[x][y] << endl;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它会编译并运行正常.
我错过了什么吗?从我读过的所有内容来看,C++不应该支持这种类型的代码.
有很多像这样的代码:
#include <stdio.h>
int main(void)
{
int a[2][2] = {{0, 1}, {2, -1}};
int *p = &a[0][0];
while (*p != -1) {
printf("%d\n", *p);
p++;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但基于这个答案,行为是不确定的.
N1570.6.5.6 p8:
当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型.如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(等效地,N +(P))和(P)-N(其中N具有值n)指向分别为数组对象的第i + n和第i-n个元素,只要它们存在.此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素.如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数.
有人可以详细解释一下吗?
此代码似乎按预期工作,使用单个指针填充数字数组
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
int arr[4], count = 0, i;
char *p, s[32] = " \t 10, 15 \n ,20, 25 , ";
p = s;
do {
arr[count++] = (int)strtol(p, &p, 10);
while (isspace(*p) || *p == ',') p++;
} while (*p);
for (i = 0; i < count; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
在strtol中使用p作为param1(source)和&p作为param 2(第一个无效字符的地址)是有效的吗?