Casting a char * to a char * [] in C - c

I'm having a problem casting, so is there a way to cast a type of:
char *result;
to a type of
char *argv[100];
?
If so, how would I do this or is there a safe way to do this?

char * result is a string
and
char * argv[100] is array of strings.
You cannot convert string into array of strings. However, you can create an array of strings where the first array value is result.
argv[0] = result;

char *result is a pointer to a char
char *argv[100] is an array of char *, so really it's a char ** (a pointer to pointers)
Keep this in mind:
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
This being the case, this is probably not what you want to be doing. I suppose the next question is: What were you trying to do? Or why?

What does result contain, and what do you expect argv to contain after the conversion?
For example, if result points to a list of strings separated by a delimiter, like "foo,bar,bletch,blurga,.., and you want each string to be a separated element in argv, like
argv[0] == "foo"
argv[1] == "bar"
argv[2] == "bletch"
argv[4] == "blurga"
then you could not accomplish this with a simple cast; you'd have to actually scan result and assign individual pointers to argv.

First, a short explanation:
char *result;
The variable result is a pointer and when set it will point to a single character. However, as you know, a single character can be the start of a string that ends with the null (\0) character.
In C, a good programmer can use the pointer result to index through a string.
However, the string's length is NOT known until the pointer reaches a null character.
It is possible to define a fixed length string of characters, in this case code:
char s[100];
Now, the fun begins. s per Kernighan and Ritchie (K&R) is a pointer to a string of characters terminated with a 0.
So, you can code:
s[0] = 'a';
*s = 'a';
s[1] = 'b';
*(s+1) = 'b';
These are equivalent statements.
As mentioned in other posts, let's add explicit parens to your argv statement:
char *(argv[100]);
Thus, this is an array of 100 pointers to characters (each of which might or might not be the start of a string of characters).

Related

What is a literal string & char array in C?

Firstly, I included C++ as C++ is just a parent of C, so I'm guessing both answers apply here, although the language I'm asking about and focusing on in this question is C, and not C++.
So I began reading the C book 'Head First C' not so long ago. In the book (page 43/278) it will answer a question for you. Are there any differences between
literal strings and character arrays.
I was totally thrown by this as I didn't know what a literal string was. I understand a string is just a array of characters, but what makes a 'string' literal? And why is it mentioning string in C if C doesn't actually provide any class (like a modern language such as C# or Java would) for string.
Can anyone help clean up this confusion? I really struggle to understand what Microsoft had to say about this here and think I need a more simple explanation I can understand.
A string literal is an unnamed string constant in the source code. E.g. "abc" is a string literal.
If you do something like char str[] = "abc";, then you could say that str is initialized with a literal. str itself is not a literal, since it's not unnamed.
A string (or C-string, rather) is a contiguous sequence of bytes, terminated with a null byte.
A char array is not necessarily a C-string, since it might lack a terminating null byte.
What is a literal string & char array in C?
C has 2 kinds of literals: string literals and compound literals. Both are unnamed and both can have their address taken. string literals can have more than 1 null character in them.
In the C library, a string is characters up to and including the first null character. So a string always has one and only one null character, else it is not a string. A string may be char, signed char, unsigned char.
// v---v string literal 6 char long
char *s1 = "hello";
char *s2 = "hello\0world";
// ^----------^ string literal 12 char long
char **s3 = &"hello"; // valid
// v------------v compound literal
int *p1 = (int []){2, 4};
int **p2 = &(int []){2, 4}; // vlaid
C specifies the following as constants, not literals, like 123, 'x' and 456.7. These constants can not have their address taken.
int *p3 = &7; // not valid
C++ and C differ in many of these regards.
A chararray is an array of char. An array may consist of many null characters.
char a1[3]; // `a1` is a char array size 3
char a2[3] = "123"; // `a2` is a char array size 3 with 0 null characters
char a3[4] = "456"; // `a3` is a char array size 4
char a4[] = "789"; // `a4` is a char array size 4
char a5[4] = { 0 }; // `a5` is a char array size 4, all null characters
The following t* are not char arrays, but pointers to char.
char *t1;
char *t2 = "123";
int *t3 = (char){'x'};

Integer warning for char pointer

Can someone help me understand why I would be getting "warning: cast to pointer from integer of different size" for the following two lines of code?
so I have a pointer to a string (char *string) and a double pointer (char **final) that needs to the store the address of the last char in string... I thought the following lines of code would work but I keep getting the error... How do I fix it?
char last = *string;
*final = (char *)last;
(char *)last
last is of type char. Casting it to a pointer means the numeric code of the character stored in last will be interpreted as an address. So if last contains A, then this will cause the value 65 to be interpreted as an address. (Assuming ASCII). The compiler is smart and indicates that this is probably not the behavior you intend.
If string is a pointer to the last character in the string, last is a copy of that character. Since it's just a copy of the value, it bears no relationship to the location in the original string. To save that pointer into what final points to, you should do:
*final = string;
To declare a variable you have to specify what type you want the variable to be, and then what you want to call the variable. If you want a variable of type "char", called "last", it can be achieved by the following syntax:
char last;
If you want a pointer to a variable of a certain data type, you add the asterisk symbol like so:
char *last;
Now you have a pointer that you can use to point at a place in memory which have to contain a char. If you are trying to create a "string" in c, that is nothing more but a series of char's, that are ordered consecutively in memory. You can use a char pointer to point at the first char in this series of char's, and then you can use specific functions that work on strings (for example strcpy or strlen), by giving this char pointer as input argument.
Now to your problem. Let's say you create a string like this:
char *str = "example";
what you have done is create a series of char's, namely
'e', 'x', 'a', 'm', 'p', 'l', 'e', '\0'
(where the '\0' is the NULL character that marks the end of the string. This is necessary for any functions working on strings to recognize where the string ends). The char pointer you have created called "str" points at the first char, that is 'e'. Remember, the pointer has the address of this char, and all the rest of the chars are stored in the address space following this first char.
To access a particular char in this string, you have to dereference the pointer "str". If you want the first char in the string, you do this:
char first = *char;
This will save the first char in a variable of type char called "first", that is in this case the letter 'e'. To get the second char you do this:
char second = *(char+1);
What you're actually doing is "reading" (dereferencing) the value that your char pointer "str" is pointing to + 1 step of size "char" in memory. In this example, this means that the variable of type char called "second" now contains (the ASCII-value representing) the second letter in the string, that is 'x'.
If you want the size of a string you can use the function strlen. The syntax is this:
int length = strlen(str);
where "str" is our char pointer that is pointing at the first char in our string (that is 'e'). strlen will return the length of the string, not including the NULL character '\0' that simply marks the end of the string. That means in our example, length will equal 7, since there are 7 letters in the word "example". If you want to extract the last letter of this string, now all you have to do is what we did before, but remember that indexing in C start at 0. This means that if you have a string of length 7, the last element of this string will be located at "index" 6. Thus, to get the last char of a string you have to do this:
char last = *(str+length-1);
or if you have not saved length to a variable of type int, you can do it like this instead:
char last = *(str+strlen(str)-1);
If you want a pointer, pointing to the last char of the string, you have to initialize a new char pointer and make it point to place (memory address) where the last char of "str" is located. By the same logic as before, this is given by the memory address of the char at "index" 6 of our original string "str". So you create a new pointer, and let that pointer point to this memory address like this:
char *last = str+strlen(str)-1;
Remember that you need to include the header file string.h at the top of your file like so:
#include <string.h>

c (and objc, and c++ and objc++) - char* argv[]

I create a clone of the echo command and that's more complicated than I was thinking.
Here my problem :
How works a char *argv[]? I know how works char myString[], but no that weird way to create strings :
It's a pointer on an array of chars, or an array of pointers on chars?
Why when I *argv[n], it shows me the n argument, not the n char... Chars can ve
char* argv[] behaves just like char** argv would behave. You could also use an char argv[][] the same way.
So basically, when you call *argv, you get argv[0] and *argv[n] gives you argv[0][n]
edit: to convert argv[x] into a std::string:
std::string s(argv[x]);
from that point on s is a standard string. But keep in mind that you must have zero terminated strings, this will not work for random binary data in a char**!
It's a pointer on an array of chars, or an array of pointers on chars?
In C, arrays are always passed as pointer to the first element. So, effectively you can treat it as char**, which is a pointer to pointer of char.
Why when I *argv[n], it shows me the n argument, not the n char... Chars can ve
You can split that expression according to the operator precedence:
char* p = argv[n];
char c = *p;

Passing string through a function (C programming)

I have just started learning pointers, and after much adding and removing *s my code for converting an entered string to uppercase finally works..
#include <stdio.h>
char* upper(char *word);
int main()
{
char word[100];
printf("Enter a string: ");
gets(word);
printf("\nThe uppercase equivalent is: %s\n",upper(word));
return 0;
}
char* upper(char *word)
{
int i;
for (i=0;i<strlen(word);i++) word[i]=(word[i]>96&&word[i]<123)?word[i]-32:word[i];
return word;
}
My question is, while calling the function I sent word which is a pointer itself, so in char* upper(char *word) why do I need to use *word?
Is it a pointer to a pointer? Also, is there a char* there because it returns a pointer to a character/string right?
Please clarify me regarding how this works.
That's because the type you need here simply is "pointer to char", which is denoted as char *, the asterisk (*) is part of the type specification of the parameter. It's not a "pointer to pointer to char", that would be written as char **
Some additional remarks:
It seems you're confusing the dereference operator * (used to access the place where a pointer points to) with the asterisk as a pointer sign in type specifcations; you're not using a dereference operator anywhere in your code; you're only using the asterisk as part of the type specification! See these examples: to declare variable as a pointer to char, you'd write:
char * a;
To assign a value to the space where a is pointing to (by using the dereference operator), you'd write:
*a = 'c';
An array (of char) is not exactly equal to a pointer (to char) (see also the question here). However, in most cases, an array (of char) can be converted to a (char) pointer.
Your function actually changes the outer char array (and passes back a pointer to it); not only will the uppercase of what was entered be printed by printf, but also the variable word of the main function will be modified so that it holds the uppercase of the entered word. Take good care the such a side-effect is actually what you want. If you don't want the function to be able to modify the outside variable, you could write char* upper(char const *word) - but then you'd have to change your function definition as well, so that it doesn't directly modify the word variable, otherwise the Compiler will complain.
char upper(char c) would be a function that takes a character and returns a character. If you want to work with strings the convention is that strings are a sequence of characters terminated by a null character. You cannot pass the complete string to a function so you pass the pointer to the first character, therefore char *upper(char *s). A pointer to a pointer would have two * like in char **pp:
char *str = "my string";
char **ptr_to_ptr = &str;
char c = **ptr_ptr_ptr; // same as *str, same as str[0], 'm'
upper could also be implemented as void upper(char *str), but it is more convenient to have upper return the passed string. You made use of that in your sample when you printf the string that is returned by upper.
Just as a comment, you can optimize your upper function. You are calling strlen for every i. C strings are always null terminated, so you can replace your i < strlen(word) with word[i] != '\0' (or word[i] != 0). Also the code is better to read if you do not compare against 96 and 123 and subtract 32 but if you check against and calculate with 'a', 'z', 'A', 'Z' or whatever character you have in mind.
the *words is even though a pointer bt the array word in function and the pointer word are actually pointing to the one and the same thing while passing arguments jst a copy of the "pointee" ie the word entered is passed and whatever operation is done is done on the pointer word so in the end we have to return a pointer so the return type is specified as *.

C notation: pointer to array of chars (string)

Why are pointers to arrays of chars (ie. strings) written as below:
char *path
Instead of:
char *path[]
or something like that?
How could I create a pointer to a char and not a string?
char *path is not a pointer to a string, it is a pointer to a char.
It may be the case that char *path semantically points to a "string", but that is just in the interpretation of the data.
In c, strings often use char *, but only under the assumption that the pointer is to the first character of the string, and the other characters are subsequent in memory until you reach a null terminator. That does not change the fact that it is just a pointer to a character.
char *path is a pointer to char. It can be used to point at a single char as well as to point at a char in a zero-terminated array (a string)
char *path[] is an array of pointers to char.
A pointer to an array of char would be char (*path)[N] where N (the size of the array) is part of the pointer's type. Such pointers are not widely used because the size of the array would have to be known at compile time.
char *path[] is an array of pointers. char *path is a single pointer.
How could I create a pointer to a char and not a string?
A 'string' in C is simply a pointer to a char that has the convention of being the start of a sequence of characters that ends in '\0'. You can declare a pointer to a single char the same way, you just have to take care to use it according to the data it's actually pointing to.
This is similar to the concept that a char in C is just an integer with a rather limited range. You can use that data type as a number, as a true/false value, or as a character that should be displayed as a glyph at some point. The interpretation of what's in the char variable is up to the programmer.
Not having a first class, full-fledged 'string' data type is something that distinguishes C from most other high level languages. I'll let you decide for yourself whether it distinguishes C in a good or a bad way.

Resources