Resumen de preguntas de la entrevista en lenguaje c integrado

Definición de puntero

Un puntero a un puntero, el puntero al que apunta es un entero
int ** a;
una matriz de 10 punteros, el puntero es un
int * a [10] que apunta a un número entero ;
un puntero tiene 10 Un puntero a una matriz de enteros
int (* a) [10]
Un puntero a una función que tiene un parámetro de número entero y devuelve un entero
int * a (int) {}
Una matriz de 10 punteros, El puntero apunta a una función que tiene un parámetro entero y devuelve un número entero
int (* a [10]) (int) // Similar a esta definición se debe realizar por descomposición. Primero defina un puntero de función única int (* a) (int), y luego una matriz de 10 punteros int (* a [10]) (int)

¿Cuál es el propósito de la palabra clave estática?


1) En el cuerpo de la función, una variable declarada como estática mantiene su valor sin cambios durante el proceso de llamada de esta función (la variable se almacena en el área de variables estáticas).
2) En el módulo (pero fuera de la función), las funciones utilizadas en el módulo pueden acceder a una variable declarada como estática, pero no otras funciones fuera del módulo. Es una variable global local.
3) En un módulo, una función declarada como estática solo puede ser llamada por otras funciones de este módulo. Es decir, esta función está restringida al ámbito local del módulo donde se declara

Constante de palabra clave


const int a; constante a
int const a; constante a
const int * a; El contenido apuntado por el puntero no se puede modificar, pero la dirección apuntada por el puntero se puede modificar.
int * const a; El lugar al que apunta el puntero no se puede cambiar, pero el contenido de la dirección apuntada se puede cambiar.
int const * const a; El contenido de la dirección apuntada por el puntero y la dirección apuntada por el puntero no se pueden modificar.

El primero establece el bit 3 de a, el segundo borra el bit 3 de un


a | = 1 << 3
a & = 0 << 3
或 BIC a, a, # 0x3

Números firmados y sin firmar


8. ¿Cuál es el resultado del siguiente código y por qué?
void foo (void)
{ unsigned int a = 6; int b = -20; (a + b> 6)? put ("> 6"): put ("<= 6"); } es mayor que 6. Un número con signo se convierte en un número sin signo. Número sin signo: no hay diferencia entre positivo y negativo, todos los bits se utilizan para representar el número en sí. Número con signo: el bit más alto se usa para indicar lo positivo y negativo del número, el bit más alto es 1 significa un número negativo y el bit más alto es 0 significa un número positivo. 1. Convierta un número sin signo en un número con signo: vea si el bit más alto del número sin signo es 1, si no es 1 (es decir, 0), el número con signo es directamente igual al número sin signo; 2. Si el número sin signo es El bit más significativo es 1, el número sin signo se complementa y el número obtenido es un número con signo. 3. Convierta un número con signo en un número sin signo: para ver si el bit más alto del número con signo es 1, si no es 1 (es decir, 0), el número sin signo es directamente igual al número con signo; 4. Si hay un número con signo El bit más alto de es 1, luego se complementará el número con signo, y el número obtenido es un número sin signo por lo que 6-20 = -14, porque el resultado se ha desbordado como número sin signo, por lo que se suma 65536 y el resultado se convierte en uno Un número positivo es 65522-5 corresponde a un número positivo 5 (00000101) → todos los bits están invertidos (11111010) → más 1 (11111011)












\ 0Pregunta

void test1 ()
{ char string [10]; char * str1 = "0123456789"; strcpy (string, str1); } // Desbordamiento y \ 0




void test2 ()
{ cadena de caracteres [10], cadena1 [10]; int i; for (i = 0; i <10; i ++) { cadena1 [i] = 'a'; } strcpy (cadena, cadena1); } str1 no tiene terminador \ 0 y el programa falla.








void test3 (char * str1)
{ char string [10]; if (strlen (str1) <= 10) { strcpy (string, str1); } } se cambia a strlen (str1) <10 Este método no reportará un error, pero Causará errores graves ocultos y modificará los datos en la memoria.





Calcule el valor de sizeof y el valor de strlen.


void func (char * str)
{ sizeof (str) =? } char str [10] = "hola"; strlen (str); 10 和 5




Problema de definición macro

#include "stdafx.h"
#define SQR (X) X * X
int main (int argc, char * argv [])
{     int a = 10;     int k = 2;     int m = 1;     a / = SQR (k + m) / SQR (k + m);     printf ("% d \ n", a);     return 0; } a = a / (k + m * k + m / k + m * k + m)







¿Cómo juzgar si un sistema operativo es de 16 bits o de 32 bits al escribir un programa en C? No se puede utilizar la función sizeof ().


int a = ~ 0; // 把 位数 全部 设为 1
if (a> 65536)  
{   cout << "32 bits" << endl; } else {   cout << "16 bits" << endl; }





Sin utilizar parámetros de terceros, intercambie los valores de los dos parámetros.


a = a + b;
b = ab;
a = ab;
alguien
a = a ^ b;
b = a ^ b;
a = a ^ b;

Operación de puntero

matriz corta sin signo [] = {1,2,3,4,5,6,7};
int i = 3;
* (matriz + i) =? El
resultado es 4.

main ()
{ int a [5] = {1,2,3,4,5}; int * ptr = (int *) (& a + 1); // (& a + 1) apunta a la siguiente matriz unidimensional printf ("% d,% d", * (a + 1), * (ptr-1)); } Solución: int * ptr = (int *) (& a + 1); & a significa obtener el primero del área de almacenamiento de la matriz a Dirección, más 1 para indicar la dirección del área de almacenamiento de la matriz a, lo que hace que el puntero ptr apunte a la dirección de la unidad de almacenamiento después del último elemento de la matriz, y después de que ptr se resta por 1, se realiza el acceso a los datos y el acceso es ptr El valor de la unidad de almacenamiento anterior del puntero, toda la respuesta final es 2, 5 (int *) (& a + 1) El tipo de puntero está obligado a convertirse.







¿Cuál es la diferencia entre #include <filename.h> e #include "filename.h"?


<> irá directamente al sistema para atravesar
"" primero atravesará el archivo de encabezado en el proyecto actual, si no existe, irá al sistema de atravesar.
<> se puede cambiar a "", pero "" no se debe cambiar a <>

Los tipos de parámetros que no se pueden usar como switch () son:


Solo se pueden utilizar números enteros como parámetros

¿Pueden las variables locales tener el mismo nombre que las variables globales?


Puede tener el mismo nombre. Los nombres de variables locales anularán los nombres de variables globales. C ++ puede usar el alcance para distinguir.
¿Se pueden definir variables globales en archivos de encabezado que pueden incluirse en varios archivos .C? ¿por qué?
¡No! Pero se puede declarar. Esto implica el problema de los símbolos fuertes y los símbolos débiles. Para obtener más información, consulte el siguiente blog.
En lenguaje C, las funciones y las variables globales inicializadas (incluida la inicialización a 0) son símbolos fuertes y las variables globales no inicializadas son símbolos débiles.
Para ellos, se utilizan las siguientes tres reglas:
① Solo puede haber un símbolo fuerte con el mismo nombre; de ​​lo contrario, el compilador informará un error de "definición duplicada".
② Se permiten un símbolo fuerte y varios símbolos débiles, pero la definición seleccionará el símbolo fuerte.
③ Cuando hay varios símbolos débiles que son iguales, el enlazador selecciona el que ocupa el mayor espacio de memoria.

Una oración da cuenta del juicio de si x es una potencia de 2.


if (x & (x-1) == 0)
    printf ("es una potencia de 2");
  else printf ("no es una potencia de 2");

pow (x, y), calcula la potencia y de
x sqrt (x), encuentra la raíz cuadrada del número de coma flotante x
fabs (x), encuentra el valor absoluto del número de coma flotante x

char * s = "AAA";
printf ("% s", s);
s [0] = 'B';
printf ("% s", s);
¿Qué ocurre?


El área constante no permite modificar el contenido, el resultado permanece sin cambios. AAA

#define MAX 256
int main ()
{ carácter sin firmar A [MAX], i; para (i = 0; i <MAX; i ++) A [i] = i; }




Char es un byte, ocho bits y el entero más grande que se puede representar es 255, por lo que aquí hay un bucle sin fin

35.struct name1
{ char str; corta x; int num; } struct name2 { char str; int num; corta x; } typedef struct  {     int a;     char b [3];     d corta;     int c;  } nodo; sizeof (nombre de estructura1) = 8 tamaño de (nombre de estructura2) = 12 tamaño de (nodo) = 16




















Alineación de bytes

int main ()
{ char a; char * str = & a; strcpy (str, "hola"); printf (str); return 0; }






No se asigna memoria para a, y a es una variable de carácter. La memoria está fuera de límites.

Operaciones de dirección y tamaño variable

unsigned char * p1;
unsigned long * p2;
p1 = (unsigned char *) 0x801000;
p2 = (unsigned long *) 0x810000;
puedo preguntar p1 + 5 = 0x801005; p2 + 5 = 0x810014;
el valor de la salida p1 + 5 es 801005 , Debido a que el carácter de valor al que apunta la variable de puntero, más uno significa que el puntero se mueve hacia atrás un byte, luego suma 5 significa que se mueve hacia atrás 5 bytes, por lo que
el valor de la entrada 801005 p5 + 5 es 801016, porque la variable de puntero apunta al entero largo Sí, agregar uno significa que el puntero se mueve hacia atrás 4 bytes, luego agregar 5 significa retroceder 20 bytes, por lo que ingrese 810014, (en hexadecimal al generar), sería 810020 en decimal 

Hay una definición de matriz int a [2] [2] = { {1}, {2,3}}, entonces el valor de a [0] [1] es 0. // Para
int (* ptr) (), ptr es el nombre de una matriz unidimensional. // Puntero de función El
puntero puede realizar operaciones>, <,> =, <=, == bajo cualquier circunstancia. // Desconocido, por lo que
c en la sentencia switch (c) puede ser de tipo int, long, char, float, unsigned int. //incorrecto. Solo puede ser un número entero, excluido el flotante.
Sin usar las funciones de la biblioteca, escriba la función int strcmp (char * source, char * dest) que devuelve 0 si es igual, y devuelve -1 si no lo es;
escriba una función int fun (char * p) para determinar si una cadena es un palíndromo y devuelve 1 si es un palíndromo , En lugar de devolver 0, devuelve -1 en caso de error

Operación variable estática

#include <stdio.h>
int suma (int a)
{ int c = 0; estático int b = 3; // 静态c + = 1; b + = 2; volver (a + b + c); } int main () { int I; int a = 2; para (I = 0; I <5; I ++) { printf ("% d,", sum (a)); } return 0; } 8,10,12,14,16,
















El que debe poder imprimir "hola" es 134, y el error es 2


char * GetHellostr (vacío);
int main (void)
{ char * ps; ps = GetHellostr (); if (ps! = NULL) { printf (ps); } return 0; } (1) char * GetHellostr (void) { char * ps = "hola"; return ps; } (2) char * GetHellostr (void) { char a [] = "hola"; return (char *) a; 内存 已经 被 释放 了} (3) char * GetHellostr (void) { static char a [] = “hola”; return (char *) a; } (4) char * GetHellostr (void) { char * ps; ps = malloc (10);































if (NULL == ps) return NULL;
strcpy (ps, "hola");
return ps;
}

Función de cadena

char * strcpy (char * strDest, const char * strSrc)
{     assert (strDest! = NULL && strSrc! = NULL);     char * strTmp = strDest;     while (* strSrc! = '\ 0')     {         * strDest ++ = * strSrc ++;     }     strDest = '\ 0';     return strTmp; }








int strlen (const char * strSrc)
{     assert (strSrc! = NULL);     int len ​​= 0;     while ((* strSrc ++)! = '\ 0')         ++ len;     return len; }





char * strcat (char * strDest, const char * strSrc)
{     assert ((strDest! = NULL) && (strSrc! = NULL));     char * strTmp = strDest;     while (* strDest! = '\ 0')         ++ strDest;     while (* strDest ++ = * strSrc ++);     * strDest ++ = '\ 0';     return strDest; }







Punteros dobles y referencias de punteros

void foo (char ** p) // 双 指针
{     * p = "después"; } int main () {     int * p = "antes";     foo (& p);     cout << p << endl; // 输出 的 为 después de     return 0; }








void foo (char * & p) // referencia de puntero
{     p = "después"; } int main () {     int * p = "antes";     foo (p);     cout << p << endl; // salida Para después de     volver 0; }








Razones para usar el lenguaje ensamblador:


Primero: la velocidad de ejecución del lenguaje ensamblador es mayor que la del lenguaje c.
Segundo: el código de inicio, al escribir el cargador de arranque y el kernel, se usa principalmente al inicializar la CPU y la memoria. Debido a que en este momento todavía no hay un entorno escrito en lenguaje C (la pila no se ha establecido), no se puede utilizar el lenguaje C.

#ifndef X
#define X
...
#endif


Evite que los archivos de encabezado se incluyan y compilen repetidamente.

La diferencia entre puntero y matriz.


La primera variedad diferente de métodos de almacenamiento es el contenido del miembro almacenado en sí. El puntero almacena la primera dirección.
El segundo es la diferencia en los métodos de cálculo. El nombre de la matriz es una constante que no se puede incrementar ni disminuir, mientras que el puntero es una variable, que se puede incrementar o decrementar.
El tercero es la operación de operación de asignación. La matriz se puede inicializar, pero la asignación general no se puede realizar a través de la instrucción de asignación y el puntero puede apuntar a otra instrucción.

¿Por qué strcpy devuelve char *


El valor devuelto por la función strcpy se puede utilizar como el parámetro real de otra función para lograr la operación en cadena.

Introducción de la CII:


Señal de inicio: cuando SCL es alto, SDA salta de alto a bajo y comienza a transmitir datos.
Señal de fin: cuando SCL es de nivel alto, SDA salta de nivel bajo a nivel alto, finalizando la transmisión de datos.
Señal de respuesta: después de recibir los datos de 8 bits, el IC que recibe los datos envía un pulso específico de bajo nivel al IC que envía los datos para
indicar que se han recibido. Después de que la CPU envía una señal a la unidad controlada, espera a que la unidad controlada envíe una señal de respuesta.
Después de recibir la señal de respuesta , la CPU determina si continuará transmitiendo la señal de acuerdo con la situación real. Si no se recibe una señal de respuesta, se considera que la
unidad controlada está defectuosa.

// IIC envía un byte
// devuelve si el esclavo
tiene una respuesta // 1, tiene una respuesta
// 0, no tiene respuesta
void IIC_Send_Byte (u8 txd)
{ u8 t; SDA_OUT (); IIC_SCL = 0; // Bajar el reloj Iniciar transmisión de datos para (t = 0; t <8; t ++) { IIC_SDA = (txd & 0x80) >> 7; txd << = 1; delay_us (2); // Para TEA5767 estos tres retardos son necesarios IIC_SCL = 1; delay_us (2); IIC_SCL = 0; delay_us (2); } } // Leer 1 byte, cuando ack = 1, enviar ACK, ack = 0, enviar nACK u8 IIC_Read_Byte (unsigned char ack) { unsigned char i, recibir = 0; SDA_IN (); // SDA se establece como entrada para (i = 0; i <8; i ++) { IIC_SCL = 0; delay_us (2); IIC_SCL = 1; recibir << = 1; si (READ_SDA) recibir ++;























delay_us (1);
}
if (! ack) IIC_NAck (); // Enviar nACK
else IIC_Ack (); // Enviar ACK
return recibir;
}

Supongo que te gusta

Origin blog.csdn.net/qq_38531460/article/details/103326672
Recomendado
Clasificación