¿Qué debe saber un programador de C? [cerrado]

11

¿Cuáles son algunos conceptos / técnicas / características de lenguaje que todo programador decente de C debería conocer / conocer (excluir ingeniería de software general y similares y centrarse solo en cosas específicas de C)? Me gustaría saber para poder llenar algunos vacíos posibles en mi conocimiento de C.

Anto
fuente
99
Comience con las preguntas C de Stack Overflow y vea si hay algo que no sepa.
chrisaycock
3
Un programador de C probablemente debería saber que2 + 2 = 4
Edward Strange
21
Deben saber de una tienda que venda zapatos a prueba de balas.
Adam Crossland
1
Hay cientos de libros escritos sobre este tema. Tu pregunta es realmente bastante vaga. Tendrás que ser más específico para obtener respuestas decentes que no sean solo una lista de cosas. Y al ver las respuestas tan lejos de esta pregunta, creo que es necesario modificarla o cerrarla.
Walter
2
¿Otro lenguaje de programación?
Muhammad Alkarouri

Respuestas:

19

¿Específico para C? Además de las construcciones estándar comunes a la mayoría de los lenguajes de procedimiento, tendría que decir:

  • (ab) utilizando el preprocesador
  • enlazador vs compilador
  • Punteros Punteros Punteros!
  • Cómo las matrices son punteros son matrices
  • Cómo funcionan las cadenas C y cómo también son punteros y matrices
  • El mal uso de la cadena C puede provocar desbordamientos del búfer
  • Cómo lanzar cualquier cosa a cualquier cosa (todo es solo 1s y 0s después de todo :))
  • Gestión manual de memoria malloc / gratis
  • Pila vs Montón
  • Alias ​​de puntero, (por qué es ilegal en C99)
  • Pensando en el desarrollo en términos de módulos (archivos .h / .c) con un conjunto de funciones expuestas públicamente en lugar de estrictamente clases
  • Sindicatos
  • ¿Por qué Sprintf puede volar tu pie?
  • Punteros de función
Doug T.
fuente
Añadiría "desbordamientos de búfer" a la lista.
Aidan Cully
@Aidan, buena captura. Adicional.
Doug T.
2
Cómo los conjuntos de C y los punteros no son lo mismo: books.google.ca/…
Matthieu
los punteros deberían haberse repetido al menos 3 veces más
Gaurav
8

Comprenda los punteros y comprenderá las computadoras.

PÁGINAS.
fuente
12
No, simplemente tendrás la ilusión de que entiendes las computadoras.
Trabajo
4

Además de la excelente respuesta de pythagras,

cómo escribir (o al menos leer) declaraciones complicadas, como char (*(*funcs[4])())[10]

funcs es una matriz [4] de punteros a una función que devuelve el puntero a la matriz [10] de caracteres

tcrosley
fuente
1
Si se vuelve tan complejo, ¿quizás esto pertenece a un comentario?
Trabajo
77
¿Tal vez debería aprender a evitar escribir así?
FabianB
3
  1. Reglas de promoción de enteros
  2. Inicializa todo a un valor conocido
  3. GOTO no es malo, especialmente cuando se usa para manejar excepciones / fallas
  4. malloc y / o calloc pueden devolver NULL ... asegúrese de que su cheque devuelva valores
  5. Las pequeñas asignaciones frecuentes de memoria pueden causar fragmentación en el montón.
  6. Aritmética de puntero
  7. Las máscaras de bits son tu amigo
  8. x >> 1 es equivalente a x / 2 para enteros sin signo
Pemdas
fuente
+1 para GOTO no ser malvado :)
zvrba
2

El programador de CA debe saber ... ¡otros idiomas! ;-) Siempre es fructífero conocer conceptos de otros lenguajes de varios paradigmas, como OOP, programación funcional, etc.

Más en serio, un vistazo al concurso de programación ofuscado es divertido y, curiosamente, también es una buena experiencia.

PhiLho
fuente
2

Mencioné "desbordamientos de búfer" en un comentario a la respuesta de Pythagras, probablemente debería aclarar un poco lo que quise decir. En C, no es suficiente saber que trabajar directamente con la memoria es peligroso; también debe comprender las formas precisas en que es peligroso. Realmente no me gusta la metáfora de "pegarse un tiro en el pie" para todos estos casos: muchas veces, no es que aprietas el gatillo, pero a menudo es un actor con intereses contrarios a los tuyos y / o de los usuarios .

Por ejemplo, en una arquitectura con una pila descendente (las arquitecturas más populares se ajustan a este proyecto de ley, generalmente se incluyen x86 y ARM), cuando se llama a una función, la dirección de retorno de la función se colocará en la pila después de las variables locales definidas en el cuerpo de la función. Entonces, si declara un búfer como una variable local y expone esa variable al mundo exterior sin verificar el desbordamiento del búfer, así:

void myFn(void) {
    char buf[256];
    gets(buf);
}

un usuario externo puede enviarle una cadena que sobrescribe la dirección de retorno de la pila; básicamente, puede cambiar la idea de tiempo de ejecución de su programa del gráfico de llamadas que conduce a la función actual. Entonces, el usuario le da una cadena que es la representación binaria de algún código ejecutable para su arquitectura, suficiente relleno para desbordar la pila myFny algunos datos adicionales para sobrescribir la dirección de retorno para myFnque apunte al código que le dio. Si esto sucede, cuando myFnnormalmente hubiera devuelto el control a su interlocutor, en su lugar se ramificará al código que proporcionó el usuario malintencionado. Si escribe código C (o C ++) que tiene el potencial de exponerse a usuarios no confiables, debe comprender este vector de ataque. Debe comprender por qué un desbordamiento del búfer contra la pila es a menudo (pero no siempre) más fácilmente explotable que uno contra el montón, y debe comprender cómo se presenta la memoria en el montón (no con demasiados detalles, necesariamente, pero el La idea de que una malloc()región ed tiene estructuras de control que la rodean puede ayudar a comprender por qué su programa se bloquea en otra malloc()o en free()).

C lo expone a detalles de bajo nivel sobre cómo funciona su máquina, y le brinda un control más directo sobre su máquina que cualquier otro lenguaje editado por el usuario en uso generalizado hoy en día. Con un gran poder viene una gran responsabilidad: realmente necesita comprender esos detalles de bajo nivel para trabajar con C de manera segura y efectiva.

Aidan Cully
fuente
0

Además de las otras buenas respuestas, me gustaría agregar técnicas de programación defensiva a la lista.

Por ejemplo, usar afirmaciones al inicio / final de las funciones para verificar el contrato.

AndersK
fuente