Summary: C language and Java

1. The difference between machine code and bytecode

1 Introduction

  • Machine code: It is a binary instruction code compiled from assembly code on a specific computer hardware platform through an assembler.
  • Bytecode: It is an intermediate code, which is a binary instruction code that is not related to a specific computer platform, compiled from Java source code through a Java compiler. Bytecode is usually run on the Java virtual machine.

2. Compilation of C and Java

The C language is a static and compiled language. Machine code is generated at compile time and executed directly at runtime, so the execution speed is very fast.

Java is an interpreted language that needs to translate the source code into bytecode before being executed by the virtual machine.

  • When a Java program is running, the Java virtual machine needs to convert bytecode into machine code to execute the program. This process is divided into two steps. First, the hot code is instantly compiled into local machine code through just-in-time compilation technology (JIT), and then the local machine code executes the operation of the program. Therefore, although bytecode is not a directly executed machine instruction, it is eventually converted into machine code to execute the program.

2. Why is the performance of C language better than Java?

1. Consumption from compilation to execution

The C language directly generates the machine code executed by the machine, while Java needs to be compiled into an intermediate code such as bytecode, and then the JVM needs to compile the bytecode into machine code for real execution when executing

2. C language does not need garbage collection mechanism

The Java garbage collector itself also consumes a lot of resources, resulting in a decrease in program performance.

For example: when a Java program is running, it takes additional time and space to check and clean up unused objects in memory. This process needs to constantly scan memory and determine which objects can be released. Due to the huge number of objects that can be processed, this process consumes a lot of time and space.

In the C language that manually releases memory, programmers can directly control the allocation and release of memory, avoiding the additional overhead of garbage collection, so that the program runs faster.

In addition, in Java, there will definitely be memory fragmentation, which also leads to low memory utilization

3. Advantages of Java and C

C language and Java have different advantages and disadvantages in terms of performance.

  • The C language is a static and compiled language. Machine code is generated at compile time and executed directly at runtime, so the execution speed is very fast. C language also allows direct access to hardware resources , which makes it very popular in the field of system programming and embedded development.
    • The C language does not have an automatic garbage collection mechanism, requiring programmers to manually manage memory . Variables and data in C language are stored in memory, and the program needs to explicitly allocate and release memory, otherwise problems such as memory leaks will occur.
      • The benefit of this is that, since no garbage collector is required, the performance is high
      • The disadvantage is that the requirements for programmers are relatively high, and they should always pay attention to codes related to memory recovery
  • In contrast, Java is an interpreted language that requires the source code to be translated into bytecode before being executed by a virtual machine.
    • Although the JIT compiler of the Java virtual machine can optimize the code according to different environments and data, its execution speed is slower than that of the C language. Java also has a garbage collection mechanism, which will affect the running speed of the program to a certain extent, especially when the memory consumption of the program is large.
    • However, Java also has its advantages. Java's object-oriented programming model, automatic memory management, strong type checking and other features make it have higher security, maintainability and portability, and can carry out large-scale software development in a more efficient way.

therefore:

  • The C language has obvious advantages in terms of performance, and is suitable for scenarios that require high speed and need to directly operate the machine hardware;
  • Java, on the other hand, is suitable for large-scale software development that requires higher security, maintainability, and portability.

4. C language direct access to hardware resource case

C language can directly access hardware resources. The reason is that C language is a static, compiled language that can directly generate machine code for execution, and allows direct manipulation of memory addresses to control hardware. Below is an example:

#include <stdio.h>
#include <conio.h>
#include <bios.h>

int main(void) {
    int ch;
    int status = _bios_keybrd(_KEYBRD_READ);
    
    printf("status = %04X\n", status);
    
    while ((ch = getch()) != ESC) {
        printf("key code: %02X\n", ch);
    }
    
    return 0;
}

This program uses the characteristics of C language, uses the _bios_keybrd function in the bios.h header file to read the keyboard state, and then performs corresponding operations according to the read results . This direct access to hardware resources is very useful in system programming and embedded development.

In contrast, Java does not support direct access to hardware resources. This is because one of the main design goals of the Java language is to ensure the security of the program and avoid security issues caused by direct access to hardware resources. In order to achieve cross-platform compatibility, the Java Virtual Machine (JVM) implements a layer of abstraction to uniformly encapsulate and manage system resources to ensure program portability and security. Therefore, Java programs cannot directly operate hardware resources, and need to indirectly operate hardware resources through specific APIs, such as Java Native Interface (JNI).

Although Java cannot directly operate hardware resources like C language, Java can still call C language functions through JNI to achieve hardware operation requirements. However, it should be noted that doing so may reduce the portability and security of Java programs, and requires manual management of memory and other issues. Therefore, it is necessary to weigh the pros and cons and choose a suitable method to operate hardware resources.

The following continues to provide some examples of C accessing hardware:

/* 案例:访问摄像头设备 */
int main()
{
    int fd;
    fd = open("/dev/video0", O_RDWR);   //以读写方式打开摄像头设备
    ioctl(fd, VIDIOC_QUERYCAP, &cap);   //查询设备属性
    ...
    close(fd);   //关闭摄像头设备
    return 0;
}

这段代码通过调用 Linux 系统提供的摄像头操作接口(open、ioctl、close)实现对摄像头设备的访问,并查询设备属性。
/* 案例:访问麦克风 */
int main()
{
    int fd;
    fd = open("/dev/dsp", O_RDONLY);   //以只读方式打开麦克风设备
    ioctl(fd, SOUND_MIXER_READ_VOLUME, &vol);  //读取音量
    ...
    close(fd);   //关闭麦克风设备
    return 0;
}

这段代码通过调用 Linux 系统提供的麦克风操作接口(open、ioctl、close)实现对麦克风设备的访问,并读取音量。
/* 案例:访问打印机 */
int main()
{
    FILE *fp;
    fp = fopen("/dev/usb/lp0", "w");   //以写方式打开打印机设备
    fprintf(fp, "Hello, printer!\n");   //向打印机写入数据
    fclose(fp);   //关闭打印机设备
    return 0;
}

这段代码通过 Linux 文件系统提供的文件操作接口(fopen、fprintf、fclose)实现对打印机设备的访问,并向打印机写入数据。

/* 案例:访问键盘 */
int main()
{
    int fd;
    struct input_event event;
    fd = open("/dev/input/event0", O_RDONLY);   //以只读方式打开键盘设备
    while(1)
    {
        read(fd, &event, sizeof(event));   //读取键盘事件
        if (event.type == EV_KEY && event.value == 1)   //判断是否为按键事件
        {
            printf("Key pressed: %d\n", event.code);   //输出按键编号
        }
    }
    close(fd);   //关闭键盘设备
    return 0;
}

这段代码通过调用 Linux 系统提供的输入设备操作接口(open、read、close)实现对键盘设备的访问,并读取键盘事件,并判断是否为按键事件,最后输出按键编号。
/* 案例:访问鼠标 */
int main()
{
    int fd;
    struct input_event event;
    fd = open("/dev/input/mice", O_RDONLY);   //以只读方式打开鼠标设备
    while(1)
    {
        read(fd, &event, sizeof(event));   //读取鼠标事件
        if (event.type == EV_REL && event.code == REL_X)   //判断是否为横向移动事件
        {
            printf("X moved: %d\n", event.value);   //输出横向移动距离
        }
    }
    close(fd);   //关闭鼠标设备
    return 0;
}

过调用 Linux 系统提供的输入设备操作接口(open、read、close)实现对鼠标设备的访问,并读取鼠标事件,并判断是否为横向移动事件,最后输出横向移动距离。
/* 案例:访问定时器 */
int main()
{
    int fd;
    struct itimerval timer;
    fd = open("/dev/rtc0", O_RDONLY);   //以只读方式打开定时器设备
    timer.it_value.tv_sec = 1;   //设置定时时间为1秒
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 1;   //设置定时周期为1秒
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL);   //设置定时器
    while(1)
    {
        ...   //执行定时任务
    }
    close(fd);   //关闭定时器设备
    return 0;
}
这段代码通过调用 Linux 系统提供的定时器操作接口(open、setitimer、close)实现对定时器设备的访问,并设置定时时间和周期,最后执行定时任务。

5. .c files and .h files in C language

The .c file refers to the C language source code file, which contains the implementation code of the C language and is the core part of the program. It can be compiled into an executable file by a compiler and run directly on the computer.

The .h file refers to the header file (Header File) , which is also a C language source code file. It contains declarations of functions, variables, and constants for sharing implementations among multiple source files. The header file is usually included in front of the .c file, and the functions and variables defined in it can be used in the .c file.

Therefore, .c files and .h files together constitute the basic structure of a C language program.

6. Macro in C language

The macro in the C language refers to a preprocessing instruction, also known as a macro definition (Macro Definition). It can replace one set of code texts with another set of code texts to simplify code and improve code reusability. Macro definitions are usually done using the #define directive.

Macros are very similar to constants in Java. They essentially represent values ​​that cannot be modified during program execution .

However, macros can be used to represent values ​​in various forms such as constants, expressions, functions, etc. Constants in Java can only represent values ​​of basic types and string types.

Macros are not type bound, so there may be some type errors. Constants in Java have type restrictions, avoiding the problem of type errors.

Use macro definitions to define constants: #define PI 3.1415926
In this way, PI can be used directly in the code instead of 3.1415926, which improves the readability and maintainability of the code.

Although the macro definition can simplify the code, it should be noted that the macro definition is only a simple text replacement, so it is easy to make mistakes that are not easy to find, such as forgetting to add parentheses to the parameters. In addition, macro definitions may reduce the readability of the code, and may also increase the size of the code. Therefore, careful consideration is required when using macro definitions.

Seven, C preprocessor

The C preprocessor is not part of the compiler, but it is a separate step in the compilation process. In short, a C preprocessor is nothing more than a text replacement tool that instructs the compiler to do the required preprocessing before actually compiling. We will abbreviate C Preprocessor as CPP .

All preprocessor commands begin with a pound sign (#) . It must be the first non-null character, and for readability, preprocessor directives should start with the first column. All important preprocessor directives are listed below:

Eight, C header file

A header file is a file with an extension  of .h  , which contains C function declarations and macro definitions, and is shared by multiple source files. There are two types of header files: header files written by programmers and header files that come with compilers.

To use a header file in a program,   it needs to be referenced using the C preprocessing directive #include .

 

Nine, C memory management 

The C language provides several functions for memory allocation and management. These functions can be found in  the <stdlib.h>  header file.

In C language, memory is managed through pointer variables . A pointer is a variable that stores a memory address that can point to a variable of any data type, including integers, floating point numbers, characters, and arrays. The C language provides some functions and operators that allow programmers to operate on memory, including allocation, release, movement, and copying.

case:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* 动态分配内存 */
   description = (char *)malloc( 30 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student.");
   }
   /* 假设您想要存储更大的描述信息 */
   description = (char *) realloc( description, 100 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcat( description, "She is in class 10th");
   }
   
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
 
   /* 使用 free() 函数释放内存 */
   free(description);
}

 When the above code is compiled and executed, it produces the following result:

Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th

Commonly used memory management functions and operators in C language

  • malloc() function: used to dynamically allocate memory. It takes one parameter, the size of the memory to be allocated in bytes, and returns a pointer to the allocated memory.

  • free() function: used to release previously allocated memory. It takes as argument a pointer to the memory to be freed and marks that memory as unused.

  • calloc() function: used to dynamically allocate memory and initialize it to zero. It takes two parameters, the number of memory blocks to allocate and the size of each memory block in bytes, and returns a pointer to the allocated memory.

  • realloc() function: used to reallocate memory. It takes two arguments, a previously allocated pointer and a new memory size, and then tries to resize the previously allocated memory block. It returns a pointer to the reallocated memory if the adjustment was successful, or a null pointer otherwise.

  • sizeof operator: Used to get the size (in bytes) of a data type or variable .

  • Pointer operator: Used to obtain the value of the memory address or variable pointed to by the pointer.

  • & Operator: Used to get the memory address of a variable.

  • * operator: used to obtain the value of the variable pointed to by the pointer.

  • -> operator: used for pointer access to structure members, the syntax is pointer->member, which is equivalent to (*pointer).member.

  • memcpy() function: used to copy data from source memory area to target memory area. It takes three parameters, a pointer to the destination memory area, a pointer to the source memory area, and the size of the data to be copied in bytes.

  • memmove() function: Similar to the memcpy() function, but it can handle overlapping memory regions. It takes three parameters, a pointer to the destination memory area, a pointer to the source memory area, and the size of the data to be copied in bytes.

Guess you like

Origin blog.csdn.net/w2009211777/article/details/130005302