我有这样的东西:
void* a[] = {(void*)"Hello",(void*)1};
cout << (char*)a[0] << endl;
cout << (int)(int64_t)((int*)a[1]) << endl;
我如何简化行 (int)(int64_t)((int *)a [1])
是否可以将void *轻松更改为int?
答案 0 :(得分:2)
void* a[] = {static_cast<void*>(const_cast<char*>("Hello")),reinterpret_cast<void*>(static_cast<omyptr_t>(1))};
std::cout << static_cast<char*>(a[0]) << std::endl;
std::cout << static_cast<int>(reinterpret_cast<intptr_t>(a[1])) << std::endl;
我认为这是所有定义的行为。
从void*
进行投射时,始终将其投射回完全相同的位置。避免使用原始C强制类型转换,因为它可以是静态的,const或重新解释强制类型转换,并且执行错误的操作确实可以破坏事情。
考虑使用std::any
或boost::any
代替原始void指针;或变体(如果您知道要存储的一组固定类型)。
答案 1 :(得分:0)
必须为void*
的数组吗? 您似乎应该只使用工会。
#include <cstdint>
#include <iostream>
union pointer_or_integer_t {
void *vp;
uintptr_t u;
intptr_t i;
};
static_assert(sizeof(void *) == sizeof(pointer_or_integer_t),
"intptr_t or uintptr_t are larger than the size as a pointer");
int main() {
pointer_or_integer_t a[] = {(void*)"Hello", {.i = 1}};
std::cout << (const char*)a[0].vp << '\n';
std::cout << a[1].i << '\n';
}
(除非您确实要强制刷新,否则请勿使用std::endl
。)
这将编译为可以完成我们想要的代码,而没有额外的开销on the Godbolt compiler explorer。
请注意,C ++中的{.i = 1}
指定初始化程序目前是GNU扩展,但将成为C ++ 20的一部分。 g ++ 8.2 -pedantic
警告:
<source>:15:50: warning: C++ designated initializers only available with -std=c++2a or -std=gnu++2a [-Wpedantic]
pointer_or_integer_t a[] = {(void*)"Hello", {.i = 1}};
^
您也可以使用void []
和uintptr_t[]
的并集,但这只有在知道大小的情况下才能轻松实现。使每个数组元素具有自己的联合效果更好。
我认为使用强制转换(而不是void*
)将联合数组转换为memcpy
到void **
数组仍然是UB,即使您使用asserts来检查它具有相同的布局。
但是,如果您有一个仅允许您传递pointer_or_integer_t **
的接口,则可以在接收函数中将其投射回void **
。如果没有代码实际索引void **
,就根本没有UB。
在实践中,如果某事物确实像void*
那样索引到对象中,通常没有问题,因为您的联合具有与android {
// more configurations
flavorDimensions "project", "environment"
productFlavors {
basic {
dimension "project"
}
advanced {
dimension "project"
}
flavorDevelopment {
dimension "environment"
applicationId "ch.myproject.app.development"
}
flavorTest {
dimension "environment"
applicationId "ch.myproject.app.test"
}
flavorIntegration {
dimension "environment"
applicationId "ch.myproject.app.integration"
}
flavorProduction {
dimension "environment"
applicationId "ch.myproject.app.production"
}
buildTypes {
debug {
testCoverageEnabled = true
minifyEnabled = false
shrinkResources = false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
debugInstantRun.initWith(buildTypes.debug)
debugInstantRun {
// we are changing this build variant later on runtime, so that it will use constant values
// for versionCode and versionName in the Manifest, for make sure the
// manifest is unchanged between the instantRun builds
// Specifies a sorted list of fallback build types that the
// plugin should try to use when a dependency does not include a
// "debugInstantRun" build type. You may specify as many fallbacks as you
// like, and the plugin selects the first build type that's
// available in the dependency.
matchingFallbacks = ['debug']
}
release {
// Currently all environments (dev/test/int/prod) are signed by the Production certificates
minifyEnabled = false
shrinkResources = false
}
}
// more configurations
} // end of android
数组相同的对象表示形式。