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é?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top