(数组和字符串)Java与C的区别

我知道C和我正在进入Java并且对它的数组和字符串方法感到困惑。 它与C中的数组和字符串完全不同。请帮助我理解C和Java之间的区别(对于字符串和数组)。

在C中,字符串通常只是一个(或指向)字符的数组,以NUL(\ 0)字符结尾。 您可以像处理任何数组一样处理字符串。

但是,在Java中,字符串不是数组。 Java字符串是java.lang.String类的实例(对象)。 它们代表字符数据,但内部实现不向程序员公开。 您不能将它们视为数组,但是,如果需要,您可以将字符串数据提取为字节或字符数组(方法getBytesgetChars )。 另请注意,Java字符始终为16位,而C中的字符通常(并非总是)为8位。

在C.

数组

C中的数组只是用于访问连续内存空间的语法糖,或者 – 在这里无耻地贬低它 – 指针符号的变体。 为了避免分配大块的连续内存并避免不得不自己重新分配内存来操作可变大小的数据,您可以采用常见的计算机科学数据结构概念(例如,链表,它使用指针来指示内存)系列中下一个元素的地址)。

您可以使用C中的数组符号替换指针算法,反之亦然。

以下将使用不同的访问方法打印数组的5个元素:

 #include  int main(int ac, char **av) { char arr[2] = {'a', 'b'}; printf("0:%c 0:%c 1:%c 1:%c\n", arr[0], *arr, arr[1], *(arr + 1)); return (0); } 

以下内容对int变量有效。 注意稍微修改以适应整数的大小:

 #include  int main(int ac, char **av) { int arr[2] = {42, -42}; printf("0:%d 0:%d 1:%d 1:%d\n", arr[0], *arr, arr[1], *(arr + 4)); return (0); } 

(要获得给定数据类型的大小,请使用sizeof 。)

字符串

在这里,我假设您想了解传统的C字符串实现,而不是第三方库提供的实现。

C中的字符串基本上只是字符数组。 这个的主要原因是显而易见的:因为你需要经常操作字符串并将它们打印到流中,使用连续的内存空间是有意义的,并且是一个简单的实现。 但是,由于您需要记住连续内存空间的大小而不是无意中访问禁止的内容,我们依赖于“以NULL结尾的字符串”的概念,这意味着N个字符的字符串实际上是N + 1的数组由尾部’\ 0’字符终止的字符,当您想要到达字符串的末尾时,该字符用作要事实的字符。

一个简单的声明是:

 char *test = "my test"; 

这相当于:

 char test[8] = { 'm', 'y', ' ', 't', 'e', 's', 't', '\0' }; 

(注意尾随’\ 0’)

但是,您必须意识到在这种情况下,字符串“my test”是静态的,这是您直接指向的内存空间。 这意味着在尝试动态修改它时会遇到问题。

例如,这会在你面前爆炸(遵循之前的声明):

 test[4] = 'H'; /* expect a violent complaint here */ 

因此,要实际修改字符串,您可以将字符串声明为:

 #include  #include  int main(int ac, char **av) { char *test = strdup("my test"); printf("%s\n", test); return (0); } 

其中strdup()是C标准库的一个函数,为你的字符串分配内存并在那里注入字符。 或者您可以使用malloc()自己分配内存并手动复制字符或使用strcpy()等函数。

因此,这个特殊的声明是可变的,你可以自由地修改字符串的内容(最后它只是一个动态分配的字符数组,用malloc()分配)。

如果您需要更改此字符串的长度(向/从中添加/删除字符),则每次都需要警惕已分配的内存。 例如,如果您尚未首先重新分配一些额外的内存,则调用strcat()将失败。 但是,有些function会为您解决此问题。

默认情况下,C字符串支持Unicode 。 您需要实现自己管理代码点,或考虑使用第三方库。


在Java中

数组

Java中的数组非常接近它们的C父级(我们甚至有一种方法可以使用裸骨本机实现来高效地进行数组到数组复制: System.arraycopy() )。 它们代表连续的内存空间。

但是,它们将这些裸骨arrays包装在一个对象中(它会跟踪数组的大小/长度)。

Java数组可以修改它们的内容,但是就像它们的C语言一样,你需要在尝试扩展它们时分配更多的内存(除了你间接地执行它,并且通常会重新分配一个完整的数组而不是像C中那样执行realloc() )。

字符串

Java中的字符串是不可变的,这意味着一旦初始化它们就无法更改,并且对String的操作实际上会创建新的String实例。 查找StringBuilderStringBuffer,以便与现有实例进行有效的字符串操作,并注意其内部实现细节(特别是在有效预先设置缓冲区容量时,以避免频繁重新分配)。

例如,以下代码用于生成someString中的第3个String实例和“另一个字符串”:

 String myNewStr = someString + "another string"; 

在底层实现中,Java String *类也使用字符数组,就像它们的C父类一样。

这意味着它们比裸骨C实现使用更多内存,因为您有实例的开销。

不仅如此,它们实际上使用了更多的内存,因为Java String类默认提供Unicode支持,这意味着它允许每个字符有多个代码点 (相比之下,在C中这不是一件容易的事)。

另一方面,请注意除了考虑性能之外,您不必担心线程,内存和实现函数寻找尾随’\ 0’字符。


还有什么?

可以说和研究更多。 您的问题目前相当广泛,但如果您在评论中添加子问题,我将很乐意进行编辑。

此外,也许这可以帮助:

  • Java语言规范,第3版,第10章 – 数组
  • 数组的JVM编译的详细信息
  • Java和C的差异 ,包括字符串和数组的详细信息。
  • C-FAQ包含指针上数组之间的一些细节相似之处和不同之处 。

arrays:

第一个明显的区别是Java不使用与C相同的声明语法。在C中,数组下标是声明符的一部分,而在Java中,它是类型规范的一部分:

 int[] arr; // Java, arr is null until array object is instantiated int arr[]; // C, incomplete declaration 

请注意,在Java中, arr存在但是为空值。 在C中, arr在出现完整声明之前不存在。

 int[][] 2Darr; // Java, arr is null until array object is instantiated int 2Darr[][]; // Illegal declaration in C; size must be specified for at least // the outer dimension 

Java中的数组对象必须使用new操作进行实例化,并且指定数组大小:

 int[] arr = new int [10]; int[][] 2Darr = new int[10][20]; 

如果数组不是基本类型,则必须单独实例化每个单独的数组元素:

 String[] strs = new String[10]; for (int i = 0; i < strs.length; i++) strs[i] = new String("some value"); 

Java中的数组表达式没有像C中的数组表达式那样“衰减”指针类型(这很方便,因为Java本身没有指针类型); Java中的数组类型是“第一类”对象,这意味着它们在任何上下文中都保留了它们的所有类型特征。 将数组对象传递给方法时,该方法接收数组对象,而不是指针。

Java数组知道它们有多大(由.length属性给出)。

字符串:

与C不同,Java提供了一种独特的String数据类型。 不要将Java字符串视为以0结尾的char数组; 他们是不同的东西。

Java String对象是不可变的; 您无法修改String对象的内容。 您可以从现有String对象的已修改内容创建新的String对象。 还有像StringBuilder和StringBuffer这样的类,允许您直接操作字符数据并创建新的String对象。

希望有所帮助。

C中的字符串只是一个字符数组。 除了惯例之外,当找到NUL字符(\ 0)时,字符串结束。

所有字符串支持都依赖于C标准库中的函数,例如strlen(),strcpy()等。

要告诉C“字符串”的大小,您必须将指针传递给单独的函数。 你可以说C中根本没有字符串,只是char数组的约定。

另一方面,Java将字符串作为语言本身的一部分构建。 Java String有方法,可以告诉你它的大小。 Java有原始类型,如C:float和int。

但它也有“Objects”和String是一种对象。

到目前为止,这与C和C ++之间的区别非常相似。

在C字符串中确实是由’\ 0’结尾的字符数组。 在Java中,string是一个类。 最好将java字符串与C ++中的std :: string进行比较,而不是C字符数组。

声明: – 在C – char str [100]; 在Java中 – String str;

在Java中,在大多数情况下,您不需要担心字符串实现,因为提供了丰富的成员函数来使用它。 在C中也有许多API,如strlen,strcpy,strcat,它们对于正常操作来说已经足够了。

当你必须做一些涉及两个字符串的操作时,主要区别在于。 例如,让我们说一个字符串给另一个。 在jave,它是直截了当的。

String str1(“This is Stack Overflow。”);
String str2;

str2 = str1;

但在C语言中,你必须使用循环来分配每个字符。 现在再一次,这并不意味着Java更快,因为内部java也做同样的事情。 只是程序员不知道这一点。

在Java中,一些操作可以使用自然运算符来完成,例如比较。

str1 == str2。

但是在C语言中你必须使用strcmp函数。

的strcmp(STR1,STR2);

简而言之,在C语言中工作时,您必须并且必须知道如何在内部操作字符串。 在Java中,你不能。

现在在C中,当您在堆区域上创建字符串时,您还必须格外小心。

char * str1 = malloc(100);

你必须使用free(str1)释放这个内存。 在Java中,程序员不需要知道堆内存或堆栈内存,所以这样的事情不会出现。

String是JAVA中的一个对象,它与C中的Character数组不同

如果你真的需要知道差异,你需要知道在p中的ptr和java中的ref之间的差异
当你在C:char str [10]中说; ==>在内存中分配一个序列10个块,每个块的大小为sizeof(char),并以null结尾,因此您可以处理具有正常ptr操作的字符串。

java:当你说String str; ==>你创建了一个对象java.lang.String,它inheritance了java.lang.String类中的一些方法,比如compare(),equals(),contains(),charAt()等等。

C:执行你用ptrs处理的正常字符串操作,或者你使用头文件中的预处理函数,里面的文件处理内存块不多也不少。
例如:比较2个字符串=> strcmp(str1,str2);

java:正如我所说的,如果你想比较2个字符串,java中的每个东西都是一个对象:
String str1;
String str2;
str1.equals(STR2);

C:一个String必须是NULL-Terminated才能知道你什么时候应该停止,如果你试图在字符串之后读取块就不会发生坏事(它会编译并且不会崩溃)

Java:正如我所说String是一个对象所以如果你试图访问String之外的元素你不需要处理内存它将抛出indexOutOfBoundException,你的程序会崩溃,除非你处理这个exception。