tamaño de tomar dos argumentos
-
27-10-2019 - |
Pregunta
En C.1.3 del C++ IS (2003.También está en C++ 11 IS), el estándar señala una diferencia entre ISO C y C++;es decir, para
char arr[100];
sizeof(0, arr)
devoluciones sizeof(char*)
en C, pero 100
en C++.
No puedo encontrar documentación para sizeof
tomando dos argumentos.La alternativa obvia es el operador de coma, pero no lo creo: sizeof(arr)
en C es 100
; sizeof(0, arr)
es sizeof(char*)
.Ambos sizeof(0, arr)
y sizeof(arr)
son 100
en C++.
Puede que me esté perdiendo todo el sentido del EI en este contexto.¿Alguien puede ayudar?Esto es similar a una pregunta discutida en 2009, pero nadie se refirió al EI y no creo que se haya dado la respuesta correcta.
Editar:En realidad, el IS está hablando del operador de coma.Entonces, por alguna razón (0, arr)
devuelve un char*
en C, pero un char[100]
en C++.¿Por qué?
Solución
En C, entonces la matriz está decayendo a un puntero, debido a la diferente especificación del operador de coma con relación a rvalues y lvalues (no es el único lugar donde se puede encontrar tal diferencia).En C ++, la matriz permanece como una matriz, produciendo el resultado correcto.
Otros consejos
En C, el operador de coma no produce un valor l, por lo que la matriz arr
que es un valor l decae en un tipo de puntero que es un rvalue (en este caso).Entonces sizeof(0,arr)
se vuelve equivalente a sizeof(char*)
, debido a valor-a-valor conversión.
Pero en C++, el operador de coma produce un valor l.No hay valor-a-valor conversión.Entonces sizeof(0,arr)
permanece igual, lo que equivale a sizeof(char[100])
.
Por cierto, sizeof
No es una función, es un operador.Entonces lo siguiente es C++ completamente válido (y C, si te imaginas printf
en lugar de cout
):
int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;
Demostración: http://www.ideone.com/CtEhn
Podrías pensar que le he pasado 4 operandos a sizeof
pero eso está mal. sizeof
opera en el resultado de los operadores de coma.Y es debido a la gran cantidad de operadores de coma que se ven muchos operandos.
4 operandos con 3 operadores de coma;al igual que en 1+2+3+4
, hay 3 operadores, 4 operandos.
Lo anterior es equivalente a lo siguiente (válido en C++0x):
auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result
Demostración: http://www.ideone.com/07VNf
Entonces es el coma operador que te hace sentir que hay muchos argumentos.Aquí coma es un operador, pero en la llamada a función, coma NO es un operador, es simplemente un separador de argumentos.
function(a,b,c,d); //here comma acts a separator, not operator.
Entonces sizeof(a,b,c,d)
opera en el tipo del resultado de ,
operadores, exactamente de la misma manera, sizeof(1+2+3+4)
opera en el tipo del resultado de +
operadores.
También tenga en cuenta que usted no puedo escribir sizeof(int, char, short)
, precisamente porque coma El operador no puede operar tipos.Opera en valor solo.Creo, sizeof
es el único operador en C y C++, que puede operar en tipos también.En C++, hay un operador más que puede operar en tipos.Su nombre es typeid
.
Es un operador de coma. Y la diferencia de la que estás hablando no tiene absolutamente nada que ver con sizeof
. La diferencia está realmente en los comportamientos de decaimiento lvalue-to-rvalue, array-to-pointer y similares entre los lenguajes C y C ++.
El lenguaje C es bastante fácil de disparar en este sentido: las matrices decaen a punteros prácticamente de inmediato (con la excepción de muy pocos contextos específicos), por lo que el resultado de la expresión 0, arr
tiene el tipo char *
. Es equivalente a 0, (char *) arr
.
En lenguaje C ++, las matrices conservan su "matriz" por mucho más tiempo. Cuando se usa en el contexto de ,
, las matrices de operadores no decaen en punteros (y los valores l no decaen en valores r), por lo que en C ++ el tipo de expresión 0, arr
sigue siendo char[100]
.
Esto es lo que explica la diferencia en el comportamiento de sizeof
en ese ejemplo. El operador ?:
es otro ejemplo de un operador que demuestra una diferencia similar en el comportamiento de descomposición, es decir, sizeof(0 ? arr : arr)
le dará resultados diferentes en C y C ++. Básicamente, todo se debe al hecho de que los operadores de C no suelen preservar el valor de sus operandos. Se pueden utilizar muchos operadores para demostrar este comportamiento.
Esto no es sizeof
tomando dos argumentos. sizeof
es un operador, no una función.
Considere eso (0, arr)
es una expresión que utiliza el operador de coma y todo lo demás encaja en su lugar.
sizeof
No se necesitan dos argumentos.Pero tampoco es una función,
Por lo tanto, el (...)
no delimites los argumentos de la función, son solo un
parte opcional de la sintaxis y aplicar la agrupación.Cuando escribessizeof(0, arr)
, el argumento para sizeof
es la única expresión 0,
arr
.Una sola expresión con un operador de coma, que evalúa el
a la izquierda de la coma, arroja su valor (pero no su
efectos secundarios), luego evalúa la expresión a la derecha de la coma,
y utiliza su valor como el valor de la expresión completa.
No estoy seguro de C, pero esto podría ser una diferencia entre el
idiomas.En C++, la conversión de matriz a puntero no se produce a menos que
es necesario;en C, si no recuerdo mal, la norma dice que
siempre tiene lugar, excepto en ciertos contextos.Incluyendo como el
operador de sizeof
.En este caso, dado que el operador de coma no
tienen restricciones con respecto a los tipos de sus operandos, el
La conversión de matriz a puntero no tiene lugar en C++.En C, un
operatand del operador de coma no aparece en las excepciones, por lo que el
Se lleva a cabo la conversión de matriz a puntero.(En este caso, la matriz
es un operando del operador de coma, y no de sizeof
.)
La mejor manera de ver qué podría estar pasando aquí es mirar la gramática del estándar.Si miramos el borrador de la sección estándar C99 6.5.3
Operadores unarios párrafo 1 podemos ver que la gramática de sizeof es:
sizeof unary-expression
sizeof ( type-name )
Entonces el segundo no se aplica pero ¿cómo se aplica el sizeof unary-expression
aplicar en este caso?Si miramos la sección A.2.1
Expresiones del borrador del estándar y trabaje en la gramática de esta manera:
unary-expression -> postfix-expression -> primary-expression -> ( expression )
obtenemos los paréntesis alrededor de un expresión y ahora sólo tenemos que mirar la gramática para operador de coma de la sección 6.5.17
operador de coma y vemos:
expression:
assignment-expression
expression , assignment-expression
Entonces ahora tenemos:
sizeof( expression , assignment-expression )
^
|
comma operator
ambos expresión y expresión-asignación puede llevarnos a Expresión primaria que tiene la siguiente gramática:
primary-expression:
identifier
constant
string-literal
( expression )
y 0
es un constante y arr
es un identificador entonces tenemos:
sizeof( constant , identifier )
Entonces, ¿qué hace el operador de coma hacer aquí?Sección 6.5.17
párrafo 2 dice:
El operando izquierdo de un operador de coma se evalúa como una expresión nula;Hay un punto de secuencia después de su evaluación.Luego se evalúa el operando correcto;el resultado tiene su tipo y valor.97)
dado que el operador de coma no es una de las excepciones en las que una matriz no se convierte en un puntero, genera un puntero (esto se trata en la sección 6.3.2.1
Valores L, matrices y designadores de funciones) lo que significa que terminamos con:
sizeof( char * )
En C++ la gramática es bastante similar, por lo que terminamos en el mismo lugar pero los operadores de coma funcionan de manera diferente.La sección del borrador del estándar de C++ 5.18
operador de coma dice:
[...] El tipo y valor del resultado son el tipo y valor del operando correcto;el resultado es de la misma categoría de valor que su operando derecho[...]
y entonces matriz a puntero La conversión no es necesaria, por lo que terminamos con:
sizeof( char[100] )
Como ya han dicho varios, y solo quiero agregar una cosa, sizeof es un operador que toma una expresión o una expresión de conversión. Por esta razón, tomé el hábito de escribir paranthesis con un tamaño de solo si es una expresión de conversión.
char *arr;
struct xxx { ... } v;
Escribiré
sizeof arr
sizeof v
pero
sizeof (struct xxx) /* Note the space after the sizeof, it's important */
sizeof (char *)
Hago lo mismo con return
sin paréntesis, ya que no es una llamada a función, y si pongo paréntesis es porque la siguiente expresión los necesita.