I have a three functions one inside another, they use the same inputs as it shown in my code, every time I printf the inputs after I pass the three functions I get a "0" as a value.
I tried to delete the "free()", as I thought it's because of it that my inputs get a 0 as values, but if I do, the code freeze.
char passcode[20];
void configuration(int **d, char *c) {
*d = malloc(sizeof(int));
**d = 1;
readn(*d, c);
return;
}
void readn(int *d, char *c) {
*d = 2;
configuration_SYS(d, c);
return;
}
void configuration_SYS(int *d, char *c) {
strcpy(c, "1234");
*d = 3;
return;
}
void main() {
int *Timeout;
configuration(&Timeout, passcode);
printf("%d\n", *Timeout);
printf("%s", passcode);
}
I expect to get a values different than 0 when I printf the two variables.
Timeout should equal 6 and passcode = "1234".
You do not need to use malloc() every time you use a pointer. malloc() allocates space for your use. NOTE: this space is not necessarily initialized (meaning that the data could be any value)
There is no need to return; at the end of a void function. The closing brace will return for you.
You call configuration_SYS(char* abc, int* d, char* c) with two arguments, yet the function takes three parameters.
As it is, I cannot compile this program. I'm not sure why it prints 0s for you. I would work on creating a Minimal Complete Verifiable Example
Related
I did not find anything about this on the man page, but cppreference.com says:
The signature of the comparison function should be equivalent to the
following:
int cmp(const void *a, const void *b);
The function must not modify the objects passed to it and must return
consistent results when called for the same objects, regardless of
their positions in the array.
Would converting the strings with strtod, atof etc. come under modification and result in undefined behavior or so?
The objective is to sort an array of char * numerically. If it is illegal, do I have to write my own sort routine?
Converting the strings pointed to by the array elements using strtod or atof is perfectly fine because neither of these functions modify their argument strings. Note that the comparison function arguments of type const void * do not point to the strings in your example, they point to individual char * elements of the array, which it must not change. What these char * pointers point to should not be changed either as this might affect the result of further comparisons involving the same string pointers, producing inconsistent results, hence causing undefined behavior in qsort.
Here is an example:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int my_compare(const void *a, const void *b) {
char * const *sa = a;
char * const *sb = b;
double xa = strtod(sa, NULL);
double xb = strtod(sb, NULL);
return isnan(xa) ? (isnan(xb) ? 0 : 1) :
isnan(xb) ? -1 :
(xa > xb) - (xa < xb);
}
int main() {
char *array[] = { "1.0", "10.0", "2.0" };
size_t n = sizeof(array) / sizeof(array[0]);
qsort(array, n, sizeof array[0], my_compare);
for (size_t i = 0; i < n; i++)
printf("%s\n", array[i]);
return 0;
}
A function should only do what it says on the tin. In this case, it should only do a comparison.
To aid this, and to try to ensure that this is all that it does, it uses the keyword const.
So if necessary just take local copies of the data. In most (all?) this is usually not necessary.
EDIT
As strtod and atof do not modify the strings, they can be used.
The function readFile(filename) reads the contents of the file and stores it in heap using malloc, it returns char* datatype. I want to store the content in an array in main so that I can count the words. How do I do so? This is the code:
int main()
{
char *char1;
char1 = readFile("test1.txt");
printf("%s", char1[0]); //This does not print anything
CountWords(*char1, &Alpha, &SentChk, &punct, &Words, &totalSents, &onlyVowel_e);
/*function header of CountWords: void CountWords(char ch, int *Alpha, int *SentChk, int *punct,
int *Words, int *totalSents, int *onlyVowel_e);*/
printf("%d", Words);
printf("%d", totalSents);
return 0;
}
When you call "Countwords", your arguments cant be seen by the main as they arent defined there. Even if you use them in your other funtion - this is a different scope. Maybe you could return a char*[] holding these paramaters you want to return. Or better yet, define all of those arguments in main, have your first function pass them "by reference". This way you have the values put in a place where you can access them later for your "Counwords"
I am getting all Zeroes in global_array_of_file2.Idea is to get the updated values from file1.c
========================file1.c===========================
#include <stdio.h>
#include <string.h>
int global_array_of_file1[10];
void func1(int a1,int b)
{
int array1_of_func1[10] = {0};
int a;
array1_of_func1[5] = 23;
array1_of_func1[6] = 34;
memcpy(global_array_of_file1,array1_of_func1,10*sizeof(int));
for (a = 0; a < 9; a++)
{
printf("from func_1 : global_array = %d \n " , global_array_of_file1[a]);
}
}
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
~
==========================file2.c======================
#include<stdio.h>
#include "file1.h"
int global_array_of_file2[10] = {0};
int main()
{
int i;
init_pointer(global_array_of_file2);
func1(3,4);
for(i = 0; i < 9 ; i++)
{
printf("global_array_of_file2 = %d \n" , global_array_of_file2[i]);
}
return 0;
}
========================file1.h===========================
void init_pointer(int *tmp);
void func1(int a,int b);
There are two issues here:
First issue is:
the code for init_pointer does nothing:
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
as tmp variable is a copy of the input variable (called by value), it does nothing.
To have it work correctly it should be something like this:
void init_pointer(int **tmp)
{
*tmp = global_array_of_file1;
}
However, as the global_array_of_file2 is declared as array, it is actually a static pointer which cannot be changed, so you cannot modify its value using statement like **tmp= global_array_of_file1.
Therefor to make it work, you should call memcpy within the init pointer method:
like this:
void init_pointer(int *tmp)
{
memcpy( tmp, global_array_of_file1, 10 * sizeof(int) );
}
The second issue, is that the code at main, first call the init_pointer (which does nothing), then it calls 'func1' which initialize the array. the order shall be the opposite. first call func1 to set the array with the appropriate values, then call the init_array method to copy this information to global array 2.
so instead of
init_pointer(global_array_of_file2);
func1(3,4);
it shall be
func1(3,4);
init_pointer(global_array_of_file2);
This is all if you want to have a copy of the global_array_file1 at file2.
If you want, you can have the same array shared between files, to do so:
at file1.h declare the array as extern:
extern int global_array_of_file1[10];
Then you can simply use it at file2.c which include file1.h
Ok I think this can be fixed easily by doing the below :
declare extern int global_array_of_file1[10] in file1.c
define int global_array_of_file1[10] = {0}; in file2.c
I then dont even need to initialize the pointer from file2.c ( no need to call init_pointer) and extra RAM too will be saved :) !
The memcpy is wrong. You just copy 10 bytes.
An int is usually 4 Bytes long (32 bit), thus you only copy parts of the array, namely the first ten bytes, thus you copy just the ints with index 0,1,2 and half of 4.
You need to copy 10 * sizeof(int)
I want to store result of type char in pointer which I'm passing as argument of function. Like this:
#include<stdio.h>
void try(char *);
int main()
{
char *result;
try(result);
printf("%s",result);
return 0;
}
void try(char *result)
{
result="try this";
}
But I'm getting result : (null)
Could someone tell me what's wrong here?
Your syntax only sends the pointer to the function. This allows changing the data the pointer points to, but not the pointer itself.
You would need to have
void try(char **result)
and call it
try(&result);
to change the actual pointer.
Another way is to copy data into the memory pointed by the pointer, but then you need to know there is enough memory available. Depends on the actual use case how to do it properly. You might use
strcpy(result, "what you want");
but then you really have to know that the memory pointed by result can handle 14 chars (remember the NULL in the end). In your current code you don't allocate memory at all for result, so this will invoke undefined behaviour.
The reason you're seeing NULL is because your compiler decided to initialize non-assigned pointers to NULL. Another compiler might initialize them to random values.
Also about terminology, you're not storing type char into a pointer. You may have a pointer pointing to a char, or in this case to a C type string, which is an array of chars.
You are creating another variable result inside try function.
Try printing result inside try function. It will work then.
If you really want to print inside main then try this -
#include<stdio.h>
void try(char **);
int main()
{
char *result;
try(&result);
printf("%s",result);
return 0;
}
void try(char** result)
{
*result = "try this";
//printf("%s\n",result);
}
Or if you don't want to get into double pointers, then this will work:
#include<stdio.h>
char* try(char *);
int main()
{
char *result;
result = try(result);
printf("%s",result);
return 0;
}
char* try(char* result)
{
result = "try this";
return result;
}
Also another way (no dynamic memory):
#include<stdio.h>
void try(char *);
int main()
{
char result[100] = {0};
try(result);
printf("%s",result);
return 0;
}
void try(char *result)
{
strcpy(result,"try this");
}
Note: When you say you got null, that doesn't mean anything - actually you had undefined behaviour there - because result was not initialized. I guess you invoked UB even before trying to print result, namely when you passed it to try. Because copy would be made in that method of the pointer, which would try to read value of original pointer - reading uninitialized variables is undefined in C. Hence always initialize your variables in C.
I see the following way of initializing a local pointer in almost every part of my code. want to understand the reason and intricacies in doing so.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize_p(char **p)
{
char *p_local = NULL;
p_local=malloc(6);
strcpy(p_local,"sandy");
*p = p_local;
}
int main(void)
{
char *p = NULL;
initialize_p(&p);
printf("Name : %s\n",p);
return 0;
}
It is just that, i am showing here with simple string. And in my actual code, it is being done using structures.
I kind of understand the above logic and also I don't. Please clear the concept involved in the above style of implementing. Also, let me know if there is any other better way of doing the same.
Please Enlighten .. :)
I'd probably return the newly allocated string instead of passing a pointer to a pointer as an argument:
char *initialize(void) {
char *init = "sandy";
char *ret = malloc(sizeof(init)+1);
if (ret != NULL)
strcpy(ret, init);
return ret;
}
int main() {
char *p = initialize();
printf("Name: %s\n", p);
free(p);
return 0;
}
In initialize_p a chunk of memory is allocated and some string is copied into the memory. In order for the caller of initializer to get the address of this new chunk of memory the address of the pointer p is passed to initialize_p:
char **p
+---+---+---+---+---+----+
*p -> | s | a | n | d | y | \0 |
+---+---+---+---+---+----+
if only the *p would have been passed then setting the pointer inside the function would be the equivalent of:
void foo(int a)
{
a=3;
...
}
a better way would be to use strdup which does the same thing as you do in your function
char* initialize_p()
{
return strdup("sandy");
}
also make sure you free the string that is returned to avoid memory leak.
I'd suggest you to create allocation and deallocation function pair
char *createP()
{
char *p = NULL;
p=malloc(6);
strcpy(p,"sandy");
return p;
}
void freeP(char *p)
{
if (p) free(p);
}
int main(void)
{
char *p = createP();
printf("Name : %s\n",p);
freeP(p);
return 0;
}
Clearing the concept? Well, in such a simple case I don't see the point in operating with byref output parameters - for me, object-oriented-like structure constructor functions are easier to understand if they work like this:
struct foo *bar = myobj_new(); // uses malloc and returns a pointer
// do something with bar
myobj_destroy(bar); // uses free
Some agree that this design is good because then the return value of the function can be used as an error/success code (have you seen SQLite3?), but I disagree. I think the primary, the most important result of a function should go through the return value, and not some auxiliary stuff. (I tend to write libraries in which failure is indicated by returning NULL and setting a byref-passed error code).
The only valid scenario I can think of is when it's more logical or symmetrical to pass arguments like this. For example, imagining a very strange sort function which is similar to the C stdlib function qsort(), but requires its comparison function itself to make the swapping of two elements when needed. The comparison function obviously needs byref access to its two parameters in order to exchange them, but it may also be useful to return the originally encountered order to the caller sort function in order to optimize the algorithm. So this comparison function could be something like:
int compare(void *a, void *b)
{
int x = *(int *)a;
int y = *(int *)b;
if (x > y)
{
*(int *)a = y;
*(int *)b = x;
return +1;
} else if (x < x) {
return -1;
}
return 0;
}
Well, pretty much that's it about my opinion...
it's an out-parameter. the function produces a result for you, and saves it to the parameter you pass. this is often used when the size of the result may vary, or if the type of the parameter is Opaque.
Personally, I think returning the result is much clearer, and is less error-prone when a dynamic allocation is required (as seen in JerryCoffin's answer +1).
when a dynamic allocation is not required, then pass it by reference (as a non-const parameter) if it is not trivially small:
struct t_struct { int a[100]; };
void InitStruct(struct t_struct* pStruct) {
pStruct->a[0] = 11;
...
}
struct t_struct s;
void InitStruct(&s);
and if it is trivially small, you may consider returning by value.