我正在研究可变函数和参数。
我注意到va_arg能够将对象转换为其他对象。例如,如果下一个参数是char
,但您使用的是va_arg
,那么它应该是int
,它会将char
转换为int
:
函数调用:
AddNumbers(3, 5, 'a', 20);
功能声明:
int AddNumbers(int count, ...) {
int result;
va_list va;
va_start(va, count);
for(int i = 0; i < count; ++i) {
result += va_arg(va, int);
}
return result;
}
所以我的问题是:这个函数使用什么样的转换(C风格,dynamic_cast等)?
答案 0 :(得分:3)
它与铸造无关。在这种情况下,它的作用是因为参数 promotion 。
使用varargs函数时,integer types smaller than int
(like e.g. char
) are promoted to int
。
这就是将字符文字传递给函数时的原因。如果您尝试其他类型,例如一个浮点值,然后它将不再起作用。
至于va_arg
宏(它主要是作为一个宏实现)的作用,它完全取决于实现。它可能根本不会进行任何投射,而是使用其他形式的type punning代替。
答案 1 :(得分:1)
如果我理解你的问题:
C在调用可变参数函数时默认执行某些“强制转换”。 GCC称这些为default argument promotions。他们是:
short int
和int
已签名或未签名float
。double
变为va_arg
。这不是AddNumbers
在 AddNumbers
内进行演员的问题。相反,在调用 AddNumbers
时,调用者将参数提升为AddNumbers
,作为将它们推送到堆栈以供public class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
onClick();
return super.onSingleTapUp(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
onDoubleClick();
return super.onDoubleTap(e);
}
@Override
public void onLongPress(MotionEvent e) {
onLongClick();
super.onLongPress(e);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
result = true;
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
}
result = true;
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
public void onClick() {
}
public void onDoubleClick() {
}
public void onLongClick() {
}
}
使用的一部分。
答案 2 :(得分:1)
它不完全是强制转换,因为va_arg
是宏,而不是函数。因此va_arg(va, int)
的类型是构造 int
。
但是在调用可变参数函数时会发生升级(省略号之前的参数除外。
所以在AddNumbers(3, 5, 'a', 20);
中,字符'a
&#39;被提升为int。然后,您可以将其用作代码所用的int,或将其转换回char(转换而非转换),因为int值可以表示为char(通过构造)