pointer producing more results than available in an array - c

include<stdio.h>
void function(int*);
int main(){
int num[]={-3,8,12,90};
function(num);
}
void function(int* array){
for(;*array!='\0';array++)
printf("\n%d",*array);
}
pointer should print elements of the array, however it keep on producing four more results.

This is a null-terminated char array, aka c-string:
const char *cstr = "Hello";
//which is same as
const char carr[] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you have for example an array of int, like in your example:
int num[] = {-3,8,12,90};
and if you want to pass that array to a function, then in addition you have to specify a length specifier, like:
void function(int* array, unsigned int len) {/*...*/} //better size_t as type
//for len (stddef.h)
call like:
function(num, sizeof num / sizeof num[0]);
Maybe it's worth to mention, that:
//'pointer to int != array of int'
int* != int[]
although, passing an array as function argument, that array decays to a pointer (see Array to pointer conversion).

Related

C Code: Pass string from one function to another function

The main problem is: as soon as I send a string from one function to another, this second function doesn't really get the string as a parameter.
In detailled:
I have a function void myfunc() contains a word. This word should be send to another function, so it can count the length of it. That's what I've written so far:
void myfunc(int (*countlength)(char ch)){
char word[10] = "Hello\n";
int result = countlength(&word);
printf("Length of word: %d\n", result);
}
The word is being send to this function countlength(char* word):
int countlength(char* word) {
int length = strlen(word);
return length;
}
However the function countlength() can't count it's length and I don't know why...
The thing is, it works when the word is in the main function. Does anybody know why my Code doesn't work?
Two mistakes:
void myfunc(int (*countlength)(char ch)){
should be
void myfunc(int (*countlength)(char* ch)){
instead, as the function accepts char pointers.
Secondly,
int result = countlength(&word);
should be
int result = countlength(word);
as word is already a char*.
What you're passing to the function doesn't match what it's expecting.
&word has type char (*)[10], i.e. a pointer to an array of size 10. The function expects a char *, so just pass word. Arrays are converted to a pointer to their first element when passed to a function, so the types will match.
This parameter declaration of a function pointer
int (*countlength)(char ch)
does not correspond to the function declaration used as an argument for this parameter
int countlength(char* word)
So you need to declare the parameter like
int (*countlength)(char *ch)
In fact the identifier ch is redundant. You could just write
int (*countlength)(char *)
That is the declaration of the function myfunc will look like
void myfunc(int (*countlength)(char *));
You declared a character array within the function like
char word[10] = "Hello\n";
So the expression used as an argument in this call
countlength(&word)
has the type char ( * )[10] instead of the expected type char *.
There is no need to use the address of operator. The array designator used as an argument in this call
countlength( word )
is implicitly converted to a pointer to the first element of the array and has the type char *.
This function
int countlength(char* word) {
int length = strlen(word);
return length;
}
does not change its argument. So it should be declared at least like
int countlength( const char* word) {
int length = strlen(word);
return length;
}
The used standard C string function strlen has the return type size_t. In general an object of the type int can be not enough large to store possible lengths of strings.
So the function should be declared like
size_t countlength( const char* word) {
return strlen(word);
}
Thus returning to the function myfunc it should look like
void myfunc( size_t ( *countlength )( const char * ) )
{
char word[10] = "Hello\n";
size_t result = countlength( word );
printf( "Length of word: %zu\n", result );
}
Well; if you use the code like this, it's working just fine
When you declare an array, its name has a type of a pointer so here word has a type of char* and it's the pointer of the array's first element
#include <stdio.h>
#include <string.h>
int countlength(char* word) {
int length = strlen(word);
return length;
}
void myfunc(){
char word[10] = "Hello\n";
int result = countlength(word);
printf("Length of word: %d\n", result);
}
main(){
myfunc();
}
Length of word: 6

Function printing list of words

I'm trying to understand what is wrong here.
void longestConsec(char* strarr[], int n) {
for(int i=0; i<n; i++)
{
printf("%s\n",strarr[i]);
}
}
int main()
{
char string[8][14] = {"zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"};
longestConsec(string, 8);
return 0;
}
I want to print every single word, and for some reason it doesn't work. What I think of is that strarr is array of pointer to char, so in every cell there should be a word, right? But when i tried to debug the code i saw that strarr and strarr[0] have different memory locations. Why?
strarr is an array of pointers to char, but string is not an array of pointers but an array of 14-element array of chars.
Pointers and 14-element array of chars may have different size, so your code won't work well.
How about using array of pointers like this?
#include <stdio.h>
void longestConsec(const char* strarr[], int n) {
for(int i=0; i<n; i++)
{
printf("%s\n",strarr[i]);
}
}
int main()
{
const char* string[8] = {"zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"};
longestConsec(string, 8);
return 0;
}
Your compiler should have given you a warning that gives a good hint.
k.c:12:19: warning: passing argument 1 of ‘longestConsec’ from incompatible pointer type [-Wincompatible-pointer-types]
12 | longestConsec(string, 8);
| ^~~~~~
| |
| char (*)[14]
k.c:2:26: note: expected ‘char **’ but argument is of type ‘char (*)[14]’
2 | void longestConsec(char* strarr[], int n) {
| ~~~~~~^~~~~~~~
string is an array of arrays, char[8][14] and strarr is a pointer to pointer to char, char **. When string is passed to the function it decays to pointer to array of 14 char, char (*)[14]. Passing multidimensional arrays to functions can be tricky, but this works:
// size_t is better than int in this case
void longestConsec(size_t len, char strarr[][len], size_t n)
{
for(int i=0; i<n; i++)
printf("%s\n",strarr[i]);
}
And then call it with:
longestConsec(sizeof string[0]/sizeof string[0][0], // 14
string,
sizeof string/sizeof string[0] // 8
);
Note that you can write sizeof string[0] instead of sizeof string[0]/sizeof string[0][0] but that's because sizeof char is always 1.
Understanding these declarations can be a bit tricky. Just to give a type example of how they are declared:
char (*arr)[10]; // arr is a pointer to array of char of size 10
char *arr[10]; // arr is an array of 10 pointers to char
Related: arrays are not pointers and pointers are not arrays

Pointer to function Prototype

i am trying to figure out what those prototypes mean
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] ,
int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
First you should find actual variable which is being declared. In all 3 examples this is fpData. Then you should start to read declaration staring from this variable moving from inside to outside.
So, let us begin with first example. We see fpData, so we say "fpData is...", then we see "*" before "fpData", so we say "fpData is pointer to...", then we see function type declaration outside of *fpData, so we say "fpData is pointer to function...". Then we should read types of arguments and result of this function.
Well, you can read types for all 3 arguments without problems. They are:
"paIndex is pointer to array of length 3 of ints"
"fpMsg is pointer to function from const char * to int"
"fpCalculation is array of length 3 of pointers to function from const char * to int"
In the last argument you should note that [3] has the higher priority than "*". I mean that while reading declaration from inside to outside you should read first array and then pointer. I. e. int *a[3] is "a is array of length 3 of pointers of int" and not "pointer to array".
Assuming all this I think you can read 2nd declaration without problems.
Now you should learn this: type of function result is written outside (i. e. BEFORE AND AFTER) of everything else.
Let us consider this:
char (*(*fp)(int))(double)
What this means? Well let's start reading, "fp is pointer to function which takes int and returns... what?" Well, we already have read (*fp)(int) part. Now we want to read everything else. And we want to understand what is result type of function we already read. And now we should note that result of function is the thing which is written OUTSIDE (i. e. BEFORE and AFTER) of everything else, i. e. outside of what we already read.
So, we have read (*fp)(int). Everything else, i. e. char (*XXX)(double) is return type for function we already read. So, well, let's continue reading. Finally we will get this:
"fp is pointer to function which gets int and returns pointer to function which gets double and returns char".
Now you can read 3rd declaration without problems
The C gibberish ↔ English link that chux posted still looks like gibberish to
me. So I'll try to sound more human:
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
This declares a function pointer fpData that returns a pointer to int. The
function takes 3 variables of the following types:
paIndex is a pointer to an int array of dimension 3. This can be used for
example when you have this:
void bar(int (*paIndex)[3])
{
}
void foo(void)
{
int fields[5][3] = { {1,1,1}, ... };
bar(fields);
}
fpMsg is a function pointer that returns an int. The function takes one
arguments only, a const char* (a string basically).
fpCalculation is an array of dimension 3 of function pointers that return
int. The functions take on argument only: a const char*.
This is a beast of a function pointer, it works in an evironment like this:
#include <stdio.h>
int msg(const char *name)
{
printf("msg: %s\n", name);
return 0;
}
int abc1(const char *name)
{
printf("abc1: %s\n", name);
return 0;
}
int abc2(const char *name)
{
printf("abc2: %s\n", name);
return 0;
}
int *scary_function(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *))
{
fpMsg("fpMsg");
fpCalculation[0]("fpCalculation0");
fpCalculation[1]("fpCalculation1");
fpCalculation[2]("fpCalculation2");
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 3; ++j)
{
printf("%-3d ", paIndex[i][j]);
}
puts("");
}
return NULL;
}
void foo(void)
{
int matrix[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12} };
int (*fpcalcs[3])(const char*) = { msg, abc1, abc2 };
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
fpData = scary_function;
// calling the function through the function pointer
fpData(matrix, msg, fpcalcs);
}
int main(void)
{
foo();
return 0;
}
The output of this is
msg: fpMsg
msg: fpCalculation0
abc1: fpCalculation1
abc2: fpCalculation2
1 2 3
4 5 6
7 8 9
10 11 12
So I've explained in detail how to parse the declaration of these function
pointers. Now try understanding the other 2 yourself, if you still have problems,
post a comment.
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (*fpCalculation[3]) (const char *));
Here, fpdata is pointer to a function which takes three arguments and returns a pointer to an integer. The arguments are as follows:
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
In this case, fpdata is array of 2 function pointers, and each function takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a pointer to an integer
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
Finally, fpdata is a pointer to a function which takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a function pointer which takes const char pointer as argument and return type is pointer to an integer.
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
it is function prototype declaration.
Where fpData is a function name, function that takes three arguments:
int (*paIndex)[3]
int (* fpMsg) (const char *)
int (*fpCalculation[3]) (const char *)
…and returns a function pointer [pointer to a function that take no argument but returns pointer to an integer].
Details :: Given function can be written as below
typedef int* (*ret_func_ptr) ();
ret_func_ptr (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));

How to assign 2D string array to char pointer array?

I've been trying to assign char words[x][y] to a char* pointer[x]. But compiler is giving me a error
array type 'char *[5]' is not assignable
pointer = &words[0]
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char words[5][10]={"Apple", "Ball", "Cat", "Dog", "Elephant"};
char *pointer[5];
pointer = &words[0];
char **dp;
dp = &pointer[0];
int n;
for(n=0; n<5; n++){
printf("%s\n", *(dp+n));
}
return 0;
}
But the code works while
char *pointer[5]={"Apple", "Ball", "Cat", "Dog", "Elephant"};
char **dp;
dp = &pointer[0];
all I need is to correctly assign the 2D array into pointer array!!
Unfortunately, you can't do it the way you want. char words[5][10] doesn't store the pointers themselves anywhere, it is effectively an array of 50 chars. sizeof(words) == 50
In memory, it looks something like:
'A','p','p','l','e','\0',x,x,x,x,'B','a'...
There are no addresses here. When you do words[3] that is just (words + 3), or (char *)words + 30
On the other hand, char *pointer[5] is an array of five pointers, sizeof(pointer) == 5*sizeof(char*).
So, you need to manually populate your pointer array by calculating the offsets. Something like this:
for (int i = 0; i < 5; i++) pointer[i] = words[i];
The error on pointer = &words[0]; happens because you are taking an 'array of pointers' and make it point to the first array of characters, since pointer points to a char this makes no sense. Try something like:
char *pointer[5];
pointer[0] = &words[0][0];
pointer[1] = &words[1][0];
//...
This will make your pointers to point at the first char of your strings (which I assume is the desired behavior?)

Assigning returned cstring to variable

I'm writing a function that reverses a cstring not in place but returns the reversed cstring. What exactly should the return type be?
#include <stdio.h>
#include <string.h>
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
int i;
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
int main()
{
char aStr[] = "hello";
char aStr2[] = "goodbye";
printf("%s %s", aStr, aStr2);
char* tmp = reverStr(aStr);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr);
return 0;
}
Gives
warning: function returns address of local variable [enabled by default]|
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]|
I tried changing char* tmp to char tmp[] but it wouldn't compile. It confuses me when I should use an array and when I should use a pointer.
revStr is an array and ceases to exist after reverStr function exits. For more please read:
Where is the memory allocated when I create this array? (C)
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
return revStr; /* Problem - revStr is a local variable trying to access this address from another function will be erroneous*/
}
const char* reverStr(const char *str)
{
const char * revStr = str;
return revStr; //ok
}
A modifiable l-value cannot have an array type. An l-value is an expression which can come on the left side of an assignment. You use an array when you want to declare lots of variables of the same type and you can index it easily since its layout will be in a sense contiguous.
You use pointers when you want to keep changing the values of the address where you variable points to.
You can do this:
char * p = "test";
p = "new";
But you cannot do this:
char p[] = "test";
char *p1 ="test1";
p = p1; //error
Because their (arrays and pointers) types are not the same and the array p is a non-modifiable l-value.
Here is your fixed code. I tried to make less modifications.
char revStr[strlen(str)]; allocates a local variable(an array) and when you are out of the scope of the reverStr function, its memory is released, which will lead any further usage of its pointer to be UB(segfault in most cases).
A correct way is to allocate the string on the heap and return its pointer like this
char* x = (char*)malloc(strlen(str));
...
return x;
This requires user to be responsible to free the memory. Or you could pass another parameter to your function for the result string.
I think you should use malloc to allocate a new string.
const char* reverStr(const char *str)
{
char *revStr;//using pointer
int i;
revStr = (char*)malloc(strlen(str));//dynamic allocation
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
An array is a pointer point to the head of continuous memory.
for example:
int a[] = {1,2,3};
The address in memory maybe:
--1000
|1|
--1004
|2|
--1008
|3|
--1012
1000, 1004, and 1012 are the value of address in memory.
Thus, the value of array a should be 1000.
printf("%d",a);// Yes, you can do it and you may get the value of 1000.
Also, you can use the following code.
int a[] = {1,2,3};
int *b;
b= a;
printf("%d",b[1]);// you will get "2".
You can consider that pointer is a set and array is in the set.
Therefore, you can NOT do this;
int a[] = {1,2,3};
int c = 0;
int *b = &c;
a = b;//error

Resources