无论代码有多糟糕,并且假设对齐等在编译器/平台上不是问题,这种未定义或破坏的行为是什么?
如果我有这样的结构: -
struct data
{
int a, b, c;
};
struct data thing;
Run Code Online (Sandbox Code Playgroud)
它是合法的访问a,b并c作为(&thing.a)[0],(&thing.a)[1]和(&thing.a)[2]?
在每种情况下,在我尝试过的每个编译器和平台上,我尝试过的每个设置都"有效".我只是担心编译器可能没有意识到b和thing [1]是相同的东西,并且'b'的存储可能被放入寄存器中,而东西[1]从内存中读取错误的值(例如).在每种情况下,我都尝试过它做了正确的事情.(我当然意识到这一点并不多见)
这不是我的代码; 它是我必须使用的代码,我对这是坏代码还是破坏代码感兴趣,因为不同影响我更改它的优先级:)
标记C和C++.我最感兴趣的是C++,但如果它不同,我也会感兴趣.
这是一个例子来说明我的问题,其中涉及一些我不能在这里发布的更复杂的代码.
#include <stdio.h>
int main()
{
int a = 0;
for (int i = 0; i < 3; i++)
{
printf("Hello\n");
a = a + 1000000000;
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序在我的平台上包含未定义的行为,因为它a会在第3个循环中溢出.
这是否会使整个程序具有未定义的行为,或者仅在溢出实际发生之后?编译器是否可能a 会解决溢出问题,因此它可以声明整个循环未定义,并且不会打扰运行printfs,即使它们都在溢出之前发生?
(标记为C和C++,即使它们不同,因为如果它们不同,我会对这两种语言的答案感兴趣.)
这个问题基于一些移植到C++的现有C代码.我只是对它是否"安全"感兴趣.我已经知道我不会这样写的.我知道这里的代码基本上是C而不是C++,但它是用C++编译器编译的,我知道标准有时略有不同.
我有一个分配一些内存的功能.我把返回的东西void*投入int*并开始使用它.
后来我把返回void*到了a Data*并开始使用它.
这在C++中是安全的吗?
示例: -
void* data = malloc(10000);
int* data_i = (int*)data;
*data_i = 123;
printf("%d\n", *data_i);
Data* data_d = (Data*)data;
data_d->value = 456;
printf("%d\n", data_d->value);
Run Code Online (Sandbox Code Playgroud)
我从来没有读过通过与存储类型不同的类型使用的变量,但担心编译器可能会看到它data_i并且data_d是不同的类型,因此不能在法律上相互别名并决定重新排序我的代码,例如将存储放在data_d第一个之前printf.哪会破坏一切.
然而,这是一直使用的模式.如果你在两次访问之间插入一个free,malloc我不相信它会改变任何东西,因为它不会触及受影响的内存本身,并且可以重用相同的数据.
我的代码被破坏了还是"正确"?
在C++中是否有任何方法可以定义一个足以容纳最多特定数字的类型,大概是使用一些聪明的模板代码.例如,我希望能够写: -
Integer<10000>::type dataItem;
Run Code Online (Sandbox Code Playgroud)
并将该类型解析为足以保持指定值的最小类型?
背景:我需要使用外部数据文件中的脚本生成一些变量定义.我想我可以使脚本看看值,然后使用uint8_t,uint16_t,uint32_t等,这取决于价值,但它似乎更优雅建设规模到生成的C++代码.
我看不出任何方法可以制作一个可以做到这一点的模板,但是知道C++模板,我确信有办法.有任何想法吗?
我正试图"现代化"一些现有的代码.
这很好用,但为了"现代化"我的代码,我认为我应该更改要定义的变量,"std::unique_ptr<Device> device_"并删除显式调用delete,这使得代码更安全,通常更好.
我的问题是这个 -
我可以调用.get来获取每个函数调用中的原始指针.但这看起来很丑陋,浪费了一些首先使用unique_ptr的原因.
或者我可以更改每个函数,以便不使用"Device*"类型的参数,而是使用"std :: unique_ptr&"类型的参数.哪个(对我来说)有点模糊了函数原型,并使它们难以阅读.
这是什么最佳做法?我错过了其他选择吗?
c ++标准库中的许多类现在都有移动构造函数,例如 -
thread::thread(thread&& t)
Run Code Online (Sandbox Code Playgroud)
但似乎std :: mutex没有.我知道它们不能被复制,但是能够从"make_mutex"函数中返回一个似乎是有意义的.(不是说它有用,只是它有意义)
有什么理由说std :: mutex没有移动构造函数吗?
我正在尝试理解c ++ 11中的内存防护,我知道有更好的方法可以做到这一点,原子变量等等,但是想知道这种用法是否正确.我意识到这个程序没有做任何有用的事情,我只是想确保fence功能的使用做了我认为他们做的事情.
基本上,该版本确保在围栏之前在此线程中所做的任何更改对于围栏之后的其他线程可见,并且在第二个线程中对变量的任何更改在围栏之后的线程中是否可见?
我的理解是否正确?或者我完全错过了这一点?
#include <iostream>
#include <atomic>
#include <thread>
int a;
void func1()
{
for(int i = 0; i < 1000000; ++i)
{
a = i;
// Ensure that changes to a to this point are visible to other threads
atomic_thread_fence(std::memory_order_release);
}
}
void func2()
{
for(int i = 0; i < 1000000; ++i)
{
// Ensure that this thread's view of a is up to date
atomic_thread_fence(std::memory_order_acquire);
std::cout << a;
}
}
int main()
{
std::thread t1 …Run Code Online (Sandbox Code Playgroud) 是否有任何安全和标准的兼容方式将C样式数组视为std :: array而不将数据复制到新的std :: array中?
这显然不能编译,但是我想要的效果(我的实际使用更复杂,但这个简短的样本应该显示我想做的事情).我想reinterpret_cast会"工作",但可能不安全?
#include <array>
int main()
{
int data[] = {1, 2, 3, 4, 5};
// This next line is the important one, treating an existing array as a std::array
std::array<int, 5>& a = data;
}
Run Code Online (Sandbox Code Playgroud)
感觉它应该是可能的,因为数据应该以相同的方式存储.
编辑:要清楚我不想清除新的std :: array,我想将现有数据称为一个.
我发现我认为在c ++中使用命名空间的"最佳实践"会损害我的代码的可读性,并让我质疑如何很好地使用它们.
我的程序由几个不同的模块组成,这些模块主要构建在"主"应用程序使用的库中.每个库都使用它自己的命名空间,它们的命名空间都在项目命名空间的"内部",以帮助预测与第三方代码的名称冲突.所以我最终得到了类名,例如"myproject :: logging :: Logger"和"myproject :: reporting :: ReportType"(作为例子).
到现在为止还挺好.在我的.cpp文件中我没有问题.我在顶部使用"使用myproject :: logging",并且可以干净地引用我的Logging类.如果我的两个命名空间之间发生冲突,我可以明确地说出我想要的那个.这很好用.
头文件虽然不同.将使用语句放入头文件中被认为是不好的做法,因为它们会影响可能不期望它们的不相关代码.所以我总是完全限定.hpp文件中的所有名称.到目前为止,这有点难看但是可以管理,所以我忍受了.但现在我正在增加在我的库中使用模板代码,这意味着现在我的.hpp文件中有更多的实际代码.由于类型名称的长度,必须完全限定每个名称使得代码几乎不可读.
我开始觉得命名空间的好处和使用它们的最佳实践开始被我不得不写的代码的不可读性所抵消.我开始怀疑我是否会更好地放弃使用命名空间来获得更易读的代码的好处,并在它们出现时修复任何名称冲突.
另一种方法是使用短的单层命名空间,而不是"myproject :: logging :: Logger",我只会使用"log :: Logger",它可以帮助很多,但会使命名空间冲突的可能性更高,而且还有命名空间传达的有用信息较少.
正如我所说,这只会影响.hpp文件中的代码,因为我很乐意在我的实现文件中使用"using namespace"来使这个可管理,但是当我在.hpp中查看我的模板化代码时它会成为一个问题.文件现在并认为"eww ...."这不可能是好的:P
有人有任何实用的建议吗?
显然,下面的代码不能用C++编译.但我有一个案例,我想基于模板参数参数化一个具有零个或多个数据项的类.
有没有什么办法可以声明一个数据成员依赖于可变参数模板参数的类,所以我可以访问它们中的每一个?或其他一些方式实现我想要的?
这是一个真正的程序,我已经解决了一个完全不同的方式,但现在我对如何做到这一点的更抽象的问题感兴趣.
template <typename... Types> class Data
{
// Declare a variable of each type in the parameter pack
// This is NOT valid C++ and won't compile...
Types... items;
};
struct Item1
{
int a;
};
struct Item2
{
float x, y, z;
};
struct Item3
{
std::string name;
}
int main()
{
Data<Item1, Item2> data1;
Data<Item3> data2;
}
Run Code Online (Sandbox Code Playgroud)