在va_arg中投射的方式

时间:2016-12-13 13:12:45

标签: c++ casting variadic-functions

我正在研究可变函数和参数。

我注意到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等)?

3 个答案:

答案 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 intint已签名或未签名float
  • double变为va_arg

这不是AddNumbersAddNumbers内进行演员的问题。相反,在调用 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(通过构造)