Difference between char* argv[] and string argv[] in C - string

What's the difference between:
int main(int argc, char* argv[])
and
int main(int argc, string argv[])
How does char* argv[] behave when compared to string argv[] and why do we need string argv[] ?
Why is string argv[] not a pointer variable in the argument here:
int main(int argc, string argv[])
{
string str = argv[1];
printf("%s\n",str);
}
where as if I use char I must use a pointer:
int main(int argc, char* argv[])
{
string str = argv[1];
printf("%s\n",str);
}

I found out what char* argv[] means and string argv[] means. They both mean the same.
To illustrate why, Let's look into the below example:
string S = "Hi!"
what exactly happens in the background while using strings?
Let's say for example:
char* S = "Hi!";
Here we create a pointer variable S that's gonna store the address of a char.
"Hi!" is stored somewhere in memory that we do not know. The address of the first character of "Hi!" is stored in S(which is the same as saying variable S points to H). In simple terms, S is storing an address(the address of character 'H'). Thus we can access all the elements one by one till we find '/0' since we know that a string ends when it finds a '/0'
If I abstract away all the details the above code can also be written as:
string S = "Hi!"
which is the same as saying char* S = "Hi!"
What if I wanna access each character then:
printf("%c", *(S)); // dereferencing the first character which is H
printf("%c", *(S+1)); // dereferencing the second character which is i
printf("%c", *(S+2)); // dereferencing the third character which is !
If I were to access each character in strings then I would say:
printf("%c", S[0]);
printf("%c", S[1]);
printf("%c", S[2]);
where both methods do the same thing. The latter is more readable than the former which is why it is commonly used.
So we can conclude that char* S is the same as string S. Since when we use strings, in the background, it uses a char pointer to access each element of the string that's stored in memory.
They both do the same thing. Using String abstracts all the details.
This solves my doubt as to why char argv[] the same as string argv[].
String argv[] does the same thing as char argv[] does but it hides the implementation and makes it easier for readability.

Related

How can I understand this code (string as a function parameter in c)

I have written this code but its not working but when I replace *targ and *sour by targ[] and sour[] then its working. Also it shows many error when I call the function converge like this converge(*targ, *sour). Please someone help me to understand this.
#include<stdio.h>
#include<string.h>
void converge(char *target, char *src);
int main()
{
char *targ = "xxxxxxxxxxxxxxxxxxx";
char *sour = "yyyyyyyyyyyyyyyyyyy";
converge(targ, sour);
//printf("%s", targ);
}
void converge(char *target, char *src)
{
int i, j;
for(i=0,j=strlen(src); i<=j; i++, j--)
{
target[i]= src[i];
target[j]= src[j];
printf("%s\n",target);
}
}
If you define a string like this:
char *targ = "abcd";
it is treated as read-only value, since the string "abcd" is stored in read-only memory, while the pointer targ is stored on your stack. Depending on your compiler you might get some warning unless you make this more explicit with const char *targ = "abcd";. An assignment like targ[i] = src[i]; is not allowed in this case.
If you define a string like this:
char targ[] = "abcd";
a char-array will be created on your data stack, this string can be changed, since data on your stack is readable and writable. Additionally you can access the first element of your array as pointer.

How to use JNI to call a "main" function that takes an array of character pointers?

hi i have an c function
int main(int argc, char *argv[])
and my wrapper.c has this function
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jint argc, jcharArray argv) {
return main(argc, argv);
}
and in java i've defined it like this
private native int lameMain(int argc, char[] argv);
but i think i'm doing something wrong with the argv-argument... it's not an char-array, but a array of char-pointers.
can anyone help?
when i run it my app crashes with
03-20 23:26:23.487: A/libc(30436): Fatal signal 11 (SIGSEGV) at 0xfd90001d (code=1), thread 30436 (package)
On the Java side, convert the array to an array of strings (i. e. String[]). Pass it like that. On the JNI side, go through the array and retrieve the characters of each string. The declarations would go like this:
private native int lameMain(String[] argv);
And in C:
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jobjectArray argv )
There's no need to pass argc, because Java arrays store their own size.
That said, you're probably doing something very wrong. Typical Android programs don't start with main and don't take command line arguments - they have activities instead. A C main() function is a starting point of a program, but since you're calling it from the Java side, it's not the first thing in the program.
EDIT: Okay, but I still think you're doing this wrong on more than one count. I take it, the encoder takes a file - right? So you save the wave from memory into a file just to be read again? That's lame (pun intended).
Also, do you really need to pass an arbitrary sized array from the Java side? If you know the number of arguments at design time, and it's small (say, two), it's much, much easier to just pass two jstrings.
Anyway, here goes the array stuff. This assumes the sources of your JNI library are C++, not C. For C, the invokation of JNI functions would be slightly different, and you'd have to use malloc/free instead of new/delete.
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jobjectArray jargv)
{ //jargv is a Java array of Java strings
int argc = env->GetArrayLength(jargv);
typedef char *pchar;
pchar *argv = new pchar[argc];
int i;
for(i=0; i<argc; i++)
{
jstring js = env->GetObjectArrayElement(jargv, i); //A Java string
const char *pjc = env->GetStringUTFChars(js); //A pointer to a Java-managed char buffer
size_t jslen = strlen(pjc);
argv[i] = new char[jslen+1]; //Extra char for the terminating null
strcpy(argv[i], pjc); //Copy to *our* buffer. We could omit that, but IMHO this is cleaner. Also, const correctness.
env->ReleaseStringUTFChars(js, pjc);
}
//Call main
main(argc, argv);
//Now free the array
for(i=0;i<argc;i++)
delete [] argv[i];
delete [] argv;
}

Conversion of CString to float

Some body help me regarding to the following problem
strFixFactorSide = _T("0.5");
dFixFactorSide = atof((const char *)(LPCTSTR)strFixFactorSide);
"dFixFactorSide" takes value as 0.0000;
How I will get correct value?
Use _tstof() instead of atof(), and cast CString to LPCTSTR, and leave it as such, instead of trying to get it to const char *. Forget about const char * (LPCSTR) while you're working with unicode and use only const _TCHAR * (LPCTSTR).
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
CString s1 = _T("123.4");
CString s2 = _T("567.8");
double v1 = _tstof((LPCTSTR)s1);
double v2 = _tstof((LPCTSTR)s2);
_tprintf(_T("%.3f"), v1 + v2);
return nRetCode;
}
and running this correctly gives the expected answer.
I think your CString strFixFactorSide is a Unicode (UTF-16) string.
If it is, the cast (const char *) only changes the pointer type, but the string it points to still remains Unicode.
atof() doesn't work with Unicode strings. If you shove L"0.5" into it, it will fetch bytes 0x30 ('0') and 0x00 (also part of UTF-16 '0'), treat that as a NUL-terminated ASCII string "0" and convert it to 0.0.
If CString strFixFactorSide is a Unicode string, you need to either first convert it to an ASCII string and then apply atof() or use a function capable of converting Unicode strings to numbers. _wtof() can be used for Unicode strings.

How can initialize bits of unsigned char?

I want to initialize bits of a variable of unsigned char with a string of binary digits, but I don't know how to do it.
From your comments, it seems like you want to parse an ASCII string of binary digits. This is how you do that:
#include <stdlib.h>
const char* binary = "10001001";
char* next;
unsigned char value = strtoul(binary, &next, 2);
if (*next) { /* conversion failed */ }
unsigned char s[] = "How now brown cow.\n";

Pointer initialization doubt

We could initialize a character pointer like this in C.
char *c="test";
Where c points to the first character(t).
But when I gave code like below. It gives segmentation fault.
#include<stdio.h>
#include<stdlib.h>
main()
{
int *i=0;
printf("%d",*i);
}
Also when I give
#include<stdio.h>
#include<stdlib.h>
main()
{
int *i;
i=(int *)malloc(2);
*i=0;
printf("%d",*i);
}
It worked(gave output 0).
When I gave malloc(0), it worked(gave output 0).
Please tell what is happening
Your first example is seg faulting because you are trying to de-reference a null pointer which you have created with the line:
int *i=0;
You can't de-reference a pointer that doesn't point to anything and expect good things to happen. =)
The second code segment works because you have actually assigned memory to your pointer using malloc which you may de-reference. I would think it's possible for you to get values other than zero depending on the memory adjacent to the address you're allocated with malloc. I say this because typically an int is 4 bytes and you've only assigned 2. When de-referencing the int pointer, it should return the value as an int based on the 4 bytes pointed to. In your case, the first 2 bytes being what you received from the malloc and the adjacent 2 bytes being whatever is there which could be anything and whatever it is will be treated as if it was an int. You could get strange behavior like this and you should malloc the size of memory needed for the type you are trying to use/point at.
(i.e. int *i = (int *) malloc(sizeof(int)); )
Once you have the pointer pointing at memory that is of the correct size, you can then set the values as such:
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
int *i = (int *)malloc(sizeof(int));
*i = 25;
printf("i = %d\n",*i);
*i = 12;
printf("i = %d\n",*i);
return 0;
}
Edit based on comment:
A pointer points to memory, not to values. When initializing char *ptr="test"; You're not assigning the value of "test", you're assigning the memory address of where the compiler is placing "test" which is placed in your processes data segment and is read only. It you tried to modify the string "test", you program would likely seg-fault. What you need to realize about a char * is that it points at a single (i.e. the first) character in the string. When you de-reference the char *, you will see 1 character and one character only. C uses null terminated strings, and notice that you do not de-reference ptr when calling printf, you pass it the pointer itself and that points at just the first character. How this is displayed depends on the format passed to printf. When printf is passed the '%c' format, it will print the single character ptr points at, if you pass the format '%p' it will print the address that ptr points. To get the entire string, you pass '%s' as the format. What this makes printf do is to start at the pointer you passed in and read each successive byte until a null is reached. Below is some code that demonstrates these.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
// Initialize to data segement/read only string
char *ptr = "test";
printf("ptr points at = %p\n", ptr); // Prints the address ptr points to
printf("ptr dereferenced = %c\n", *ptr); // Prints the value at address ptr
printf("ptr value = %s\n", ptr); // Prints the string of chars pointed to by ptr
// Uncomment this to see bad behavior!
// ptr[1] = 'E'; // SEG FAULT -> Attempting to modify read-only memory
printf("--------------------\n");
// Use memory you have allocated explicitly and can modify
ptr = malloc(10);
strncpy(ptr, "foo", 10);
printf("ptr now points at = %p\n", ptr); // Prints the address ptr points to
printf("ptr dereferenced = %c\n", *ptr); // Prints the value at address ptr
printf("ptr value = %s\n", ptr); // Prints the string of chars pointed to by ptr
ptr[1] = 'F'; // Change the second char in string to F
printf("ptr value (mod) = %s\n", ptr);
return 0;
}

Resources