r****o 发帖数: 1950 | 1 typedef struct
{
...
}s_t;
s_t a1;
volatile s_t a2;
...
//assume a1 is initiliazed with some value, and we want to copy its value to
a2
memcpy(&a2, &a1, sizeof(s_t));
这里能直接这么用memcpy吗?会有什么问题呢?
正确的写法应该怎么写? |
t****t 发帖数: 6806 | 2 i supppose not, since memcpy only take void* or const void*. volatile void*
doesn't convert to void* implicitly. so you have to do an explicit cast.
to
【在 r****o 的大作中提到】 : typedef struct : { : ... : }s_t; : s_t a1; : volatile s_t a2; : ... : //assume a1 is initiliazed with some value, and we want to copy its value to : a2 : memcpy(&a2, &a1, sizeof(s_t));
|
F********g 发帖数: 475 | |
s*****n 发帖数: 5488 | 4 面试题吗?volatile const指针不可以用于memcpy.
如果是外设的寄存器,memcpy过去你就惨了。考虑到外设非常可能在并发的工作。
一个字节一个字节的copY?
to
【在 r****o 的大作中提到】 : typedef struct : { : ... : }s_t; : s_t a1; : volatile s_t a2; : ... : //assume a1 is initiliazed with some value, and we want to copy its value to : a2 : memcpy(&a2, &a1, sizeof(s_t));
|
r****o 发帖数: 1950 | 5 谢谢,你是说在memcpy里面的参数里面加cast?
memcpy((volatile *)&a2, &a1, sizeof(s_t));
还有你看这样行不行?
typedef volatile struct
{
...
}s_t;
s_t a1;
s_t a2;
memcpy(&a2, &a1, sizeof(s_t));
这样a1,a2都是volatile,是不是就可以用memcpy了?
a1本来不必是volatile,但是加上volatile是不是也没有大问题?只是多了一点
overhead而已?
*
////////////
typedef struct
{
...
}s_t;
s_t a1;
volatile s_t a2;
...
//assume a1 is initiliazed with some value, and we want to copy its value to
a2
memcpy(&a2, &a1, sizeof(s_t));
这里能直接这么用memcpy吗?会有什么问题呢?
正确的写法应该怎么写?
【在 t****t 的大作中提到】 : i supppose not, since memcpy only take void* or const void*. volatile void* : doesn't convert to void* implicitly. so you have to do an explicit cast. : : to
|
S**I 发帖数: 15689 | 6 你没明白thrust的意思。memcpy的prototype是
void * memcpy ( void * destination, const void * source, size_t num )
&a2的类型要被cast成void *,&a1的类型要被cast成const void *,a2(和a1)的类型
是volatile,所以cast可能需要是explicit的。
你应该写成
memcpy((void *)&a2, (const void *)&a1, sizeof(s_t))
void
to
【在 r****o 的大作中提到】 : 谢谢,你是说在memcpy里面的参数里面加cast? : memcpy((volatile *)&a2, &a1, sizeof(s_t)); : 还有你看这样行不行? : typedef volatile struct : { : ... : }s_t; : s_t a1; : s_t a2; : memcpy(&a2, &a1, sizeof(s_t));
|
r****o 发帖数: 1950 | 7 多谢,
是不是如果a1,a2都不是volatile,memcpy会implicit的进行(void *)和(const void *
)的cast。
但是如果a2是volatile,那么就必须进行(const void *)的cast。
进行了这个cast之后,是不是就能把一个non-valatile的结构copy给valatile的结构了?
【在 S**I 的大作中提到】 : 你没明白thrust的意思。memcpy的prototype是 : void * memcpy ( void * destination, const void * source, size_t num ) : &a2的类型要被cast成void *,&a1的类型要被cast成const void *,a2(和a1)的类型 : 是volatile,所以cast可能需要是explicit的。 : 你应该写成 : memcpy((void *)&a2, (const void *)&a1, sizeof(s_t)) : : void : to
|
S**I 发帖数: 15689 | 8
*
了?
是
【在 r****o 的大作中提到】 : 多谢, : 是不是如果a1,a2都不是volatile,memcpy会implicit的进行(void *)和(const void * : )的cast。 : 但是如果a2是volatile,那么就必须进行(const void *)的cast。 : 进行了这个cast之后,是不是就能把一个non-valatile的结构copy给valatile的结构了?
|
r****o 发帖数: 1950 | 9 谢谢,不过我还是没弄明白为什么有volatile就必须进行explicit cast。能再说说吗? |
r****o 发帖数: 1950 | 10 谢谢,不过我还是没弄明白为什么有volatile就必须进行explicit cast。能再说说吗? |
|
|
S**I 发帖数: 15689 | 11 C++标准里没说volatile的指针可以implicitly cast,是否必须explicitly cast就要
看具体的实现了。有的编译器允许implicitly cast,但是会给warning,有的就不允许。
吗?
【在 r****o 的大作中提到】 : 谢谢,不过我还是没弄明白为什么有volatile就必须进行explicit cast。能再说说吗?
|
t****t 发帖数: 6806 | 12 规定就是这样的, you can add more qualifier implicitly, not the other way.
吗?
【在 r****o 的大作中提到】 : 谢谢,不过我还是没弄明白为什么有volatile就必须进行explicit cast。能再说说吗?
|
r****o 发帖数: 1950 | 13 多谢,除了volatile还有什么其他类型的指针需要exlicitly cast吗?
许。
【在 S**I 的大作中提到】 : C++标准里没说volatile的指针可以implicitly cast,是否必须explicitly cast就要 : 看具体的实现了。有的编译器允许implicitly cast,但是会给warning,有的就不允许。 : : 吗?
|
t****t 发帖数: 6806 | 14 事实上, 允许implicit cast的都列出来了, 没列出来的都是非法的.
许。
【在 S**I 的大作中提到】 : C++标准里没说volatile的指针可以implicitly cast,是否必须explicitly cast就要 : 看具体的实现了。有的编译器允许implicitly cast,但是会给warning,有的就不允许。 : : 吗?
|
r****o 发帖数: 1950 | 15 谢谢,C标准也是这样的吗?
许。
【在 S**I 的大作中提到】 : C++标准里没说volatile的指针可以implicitly cast,是否必须explicitly cast就要 : 看具体的实现了。有的编译器允许implicitly cast,但是会给warning,有的就不允许。 : : 吗?
|
k****e 发帖数: 126 | 16 C99里面对function call是这样规定的,6.5.2.2 Function calls:
If the expression that denotes the called function has a type that does
include a prototype, the arguments are implicitly converted, as if by
assignment, to the types of the corresponding parameters, taking the type of
each parameter to be the unqualified version of its declared type.
对于assignment是这样规定的,6.5.16.1 Simple assignment:
one operand is a pointer to an object or incomplete type and the other is a
pointer to a qualified or unqualified version of void, and the type pointed
to by the left has all the qualifiers of the type pointed to by the right;
最后一句话说的就是lz这种情况了,所以在赋值语句左边的指针所指向的数据类型必须
包含赋值语句右边指针所指向的数据类型的所有qualifiers,只有符合这种前提的时候
才可以做隐性类型转换。
memcpy的原型是void * memcpy ( void * destination, const void * source, size_
t num )
你的这句话“memcpy(&a2, &a1, sizeof(s_t));”中,&a2的类型是(volatile s_t *
),不可以直接赋值给类型为(void *)的指针,因此这种simple assignment不适用于
你的这个function call,需要做显性类型转换。
【在 r****o 的大作中提到】 : 谢谢,C标准也是这样的吗? : : 许。
|
r****o 发帖数: 1950 | 17 非常感谢!
也感谢thrust和SETI的回答。
of
a
pointed
【在 k****e 的大作中提到】 : C99里面对function call是这样规定的,6.5.2.2 Function calls: : If the expression that denotes the called function has a type that does : include a prototype, the arguments are implicitly converted, as if by : assignment, to the types of the corresponding parameters, taking the type of : each parameter to be the unqualified version of its declared type. : 对于assignment是这样规定的,6.5.16.1 Simple assignment: : one operand is a pointer to an object or incomplete type and the other is a : pointer to a qualified or unqualified version of void, and the type pointed : to by the left has all the qualifiers of the type pointed to by the right; : 最后一句话说的就是lz这种情况了,所以在赋值语句左边的指针所指向的数据类型必须
|
S**I 发帖数: 15689 | 18 我拿几个编译器试了一下,默认的编译设置下,所有的编译器都是给warning,但是允
许通过:
GCC 4.8
LLVM-GCC 4.2.1
Clang
ICC
Visual C++
GCC 4.8, LLVM-GCC 4.2.1和Clang的warning message里明确说明编译的时候volatile
给去掉了,ICC和VC没说,不过我估计实现也差不多。
【在 t****t 的大作中提到】 : 事实上, 允许implicit cast的都列出来了, 没列出来的都是非法的. : : 许。
|
d***a 发帖数: 13752 | 19 C语言中volatile的意思,是指除当前程序之外,此变量有可能被系统其它部分(例如
中断或信号handler或I/O硬件)改变。
如果这个结构真的是volatile,那么有可能在memcpy运行到一半时,内存的内容改变了
(比如说发生了中断,修改了结构内容)。拷出去的结构内容,一部分是旧的,一部分
是新的,这样最后的内容就错了。加casting可以防止编译器报错,但运行时还是会出
问题。
如果volatile是你自己加的,其实这个结构并不volatile,那就不用担心了。
to
【在 r****o 的大作中提到】 : typedef struct : { : ... : }s_t; : s_t a1; : volatile s_t a2; : ... : //assume a1 is initiliazed with some value, and we want to copy its value to : a2 : memcpy(&a2, &a1, sizeof(s_t));
|
r****o 发帖数: 1950 | 20 谢谢。我在memcpy前后有中断关闭和恢复,应该可以防止这种错误。
【在 d***a 的大作中提到】 : C语言中volatile的意思,是指除当前程序之外,此变量有可能被系统其它部分(例如 : 中断或信号handler或I/O硬件)改变。 : 如果这个结构真的是volatile,那么有可能在memcpy运行到一半时,内存的内容改变了 : (比如说发生了中断,修改了结构内容)。拷出去的结构内容,一部分是旧的,一部分 : 是新的,这样最后的内容就错了。加casting可以防止编译器报错,但运行时还是会出 : 问题。 : 如果volatile是你自己加的,其实这个结构并不volatile,那就不用担心了。 : : to
|
d***a 发帖数: 13752 | 21 对,单核单进程程序,就是这个解决方法。多核多进程程序,就得用同步了。
【在 r****o 的大作中提到】 : 谢谢。我在memcpy前后有中断关闭和恢复,应该可以防止这种错误。
|