I've been working on a method which is supposed to convert a Pascal string to a C String. I was also told that the char * returned should point to a newly allocated char array containing a null-terminated C-String. The callee is responsible for calling free() on this array.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *pascal_convert(void *x)
{
int *y;
x = y;
char *z;
*z = *((int*)x);
char *arr = malloc(sizeof(*z));
for (int i = 0; i < *y; i++)
{
arr[i] = z[i];
}
char* fin = arr;
return fin;
}
Many adjustments needed
char *pascal_convert(void *x)
{
// int *y;
// x = y; This assignment is backwards
unsigned char *y = x; // Need unsigned char (unless your pascal uses wider type here)
// y = z;
// char *z;
// *z = *((int*)x);
size_t size = *y++; // Size is just the first element
// char *arr = malloc(sizeof(*z));
char *arr = malloc(size + 1); // Allocate + 1 for the null chacter
if (arr) { // test need as `malloc()` may fail
// for (int i = 0; i < *y; i++) { arr[i] = z[i]; }
memcpy(arr, y, size);
arr[size] = '\0'; // append null character
}
// char* fin = arr; // No need for new variable
// return fin;
return arr;
}
Related
I managed to put the value in the pointer while in the function, However when i come back to the main i just dont get the values. Where am i wrong? sending parameters wrong? wrong allocation? Here's the code:
bool wc(int* nlines, int* nwords, int* nchars)
{
int lines=5,chars=6,words=7;
nchars = (int *) malloc(chars*sizeof(int));
*nchars = chars;
nlines = (int *) malloc(lines*sizeof(int));
*nlines = lines;
nwords = (int *) malloc(words*sizeof(int));
*nwords = words;
}
int main() {
int* chars; int* words; int* lines;
int res = wc(&lines,&words,&chars);
printf("%d %d %d\n",chars,lines,words);
return 0;
}
If all you want to do is be able to set 3 int values inside a function then this is how I would so it.
#include <stdio.h>
#include <stdbool.h>
bool wc(int* nlines, int* nwords, int* nchars)
{
int lines=5,chars=6,words=7;
*nchars = chars;
*nlines = lines;
*nwords = words;
return true;
}
int main() {
int lines = 0;
int words = 0;
int chars = 0;
int res = wc(&lines,&words,&chars);
printf("%d %d %d\n",chars,lines,words);
return 0;
}
If for some reason you must use pointers as shown in your example then this will do what you want.
#include <stdio.h>
#include <stdbool.h>
bool wc(int** nlines, int** nwords, int** nchars)
{
int lines=5,chars=6,words=7;
*nchars = malloc(sizeof(int));
**nchars = chars;
*nlines = malloc(sizeof(int));
**nlines = lines;
*nwords = malloc(sizeof(int));
**nwords = words;
return true;
}
int main() {
int* chars; int* words; int* lines;
int res = wc(&lines,&words,&chars);
printf("%d %d %d\n",*chars,*lines,*words);
free(chars);
free(words);
free(lines);
return 0;
}
As you can see this just means you need to add a bunch more * all over the place.
In C function input variables are passed by value, not reference. So when you assign them locally, the value in the caller scope is unaffected. E.g.
void foo(int a) {
a = 5;
}
int main() {
int b = 3;
foo(b);
// here, b is still 3
}
This is exactly what you are doing in your example, though your variables are not int, but int*.
If your input variable is a pointer though, you can change the memory that the variable points to, and this will obviously reflect in the calling scope. E.g.
void foo(int *a) {
*a = 5;
}
int main() {
int b = 3;
foo(&b);
// here, b is 5
}
In your case, you want to allocate pointers, so you want your function signature to be a pointer to a pointer. E.g.
void foo(int **a) {
*a = malloc(sizeof(int));
}
int main() {
int* b = NULL;
foo(&b);
// here, b is allocated to a valid heap area
free(b);
}
I want to access the pointer to an array of pointers
I am successfullay able to map the top and the bottom block
unsigned int *outputAddress = NULL;
unsigned int *outputOffsetAddress = NULL;
unsigned int *OutputptrptrAddr = NULL;
unsigned int *PtrArr[250];
unsigned int **val = PtrArr;
void MemoryMapping(unsigned int outputOffsetRTI)
{
unsigned int *memBase;
memBase = (unsigned int *)malloc(2000);
outputAddress = (unsigned int *)(memBase + outputOffsetRTI);
for (int x = 0; x < 5; x++)
{
*outputAddress = 123;
*outputAddress++;
}
outputAddress = outputAddress - 5;
for (int x = 0; x < 5; x++)
{
PtrArr[x] = (unsigned int *)outputAddress;
outputAddress += 1;
}
outputOffsetAddress = outputAddress + 250;
for (int x = 0; x < 5; x++)
outputOffsetAddress[x] = (unsigned int)PtrArr[x];
}
How to tranverse through the input pointer block to get all values from the input block?
You need to dereference (e.g. *ptr) to access a value through a pointer. The following block illustrates the access you mention. But using triple pointers is not a good idea: Triple pointers in C: is it a matter of style?
// This is the pointer to an array of pointers
unsigned int *** input;
// Dereference it to get the array base
unsigned int ** ptr_array = *input;
// You can use a temporary pointer to iterate over the array
unsigned int * ptr;
// This will be the data pointed to
unsigned int data;
// You need to know the array size as well, assuming it is 5 here
for (int x=0; x<5; x++) {
// The array contains pointers
ptr = ptr_array[x];
// Dereference the pointer to reach the data
data = *ptr;
}
** I would like to copy the pointer array to a new pointer so the original array won't change**
/* The main contains a pointer (p) to an array */
int main()
{
...
...
...
p = (int*)malloc(length*sizeof(int));
z = (int*)copyArray(p, length);
printArray(z, length);
return 0;
}
/* end of main */
CopyArray func
/* copy the array, return a new pointer to a new array with same size and values */
int copyArray(int *p, int length)
{
int *z = (int*)malloc(length*sizeof(int));
for(length--; length>=0; length--)
{
z[length] = p[length];
}
return *z;
}
printArray func
/* The function receives a pointer to an array and it's length. it will print the values that the array contains by the order */
void printArray(int *p, int length)
{
int i = 0;
for(; i<length; i++)
{
printf("\n %d \n", p[i]);
}
}
Reason for not working : return *z; here you are returning only one element *(z+0) = z[0] not the whole array. Check the code below:
#include <stdio.h>
#include <stdlib.h>
int *copyArray(int *p, int length) // Change return type to `int *`
{
int *z = malloc(length * sizeof(int)); // No need to cast output of malloc
for (length--; length >= 0; length--)
{
z[length] = p[length];
}
return z; // return the pointer.
}
void printArray(int *p, int length)
{
int i = 0;
for (; i < length; i++)
{
printf("\n %d \n", p[i]);
}
}
int main()
{
int *p;
int *z;
int length =5;
p = malloc(length*sizeof(int)); // No need of casting
for(int i=0 ;i<length; i++)
{
p[i] = i; // assigning some values
}
z = copyArray(p, length); // Donot cast return of the function
printArray(z, length);
return 0;
}
The output is :
0
1
2
3
4
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X** a, int size){
for (int i = 0;i < size; i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container = (struct X*)malloc(sizeof(struct X) * n);
read_record(&container, n);
}
I created a 1D array of size n, then I passed it by reference to the function read_record. However, when I execute the program, there is a segmentation fault. What is the problem?
EDIT:
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. That's why I want to send the array as a reference. If I did it in main then I would write:
container = realloc(container, (n + 10) * sizeof(Struct X));
How can I do this in the function?
container is already a pointer, you don't need to pass the address-of the pointer, instead:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X *a, size_t size)
{
for (size_t i = 0; i < size; i++) {
a[i].deg = 0;
}
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
read_record(container, n);
}
also, prefer size_t to store the number of allocated objects.
Nitpick: read_record doesn't seem a good name for a function that modifies the contents of the records.
EDIT: As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
Same approach but returning a reallocated container:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
struct X *read_record(struct X *a, size_t size)
{
struct X *new = realloc(a, sizeof(struct X) * size);
if (new != NULL)
{
for (size_t i = 0; i < size; i++) {
new[i].deg = 0;
}
}
return new;
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
container = read_record(container, n * 2);
if (container == NULL)
{
fprintf(stderr, "Can't read record\n");
exit(EXIT_FAILURE);
}
}
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
The pointer is passed by value, so to save the changes and have them usable outside the function scope, after the function ends, i.e. in main, a pointer to pointer must be the argument, and the address of the pointer must be passed, your overall assessment is correct.
Your implementation, however, is not correct, here's how you shoud do it:
Live demo
void read_record(struct X **a, int size) //double pointer
{
*a = realloc(*a, sizeof **a * (size + 10)); //reallocate memory for 20 ints
if (*a == NULL)
{
perror("malloc");
}
for (int i = 0; i < size + 10; i++) //assing new values
{
(*a)[i].deg = 1;
}
}
int main()
{
int n = 10;
struct X *container = malloc(sizeof *container * n); //original allocation
//the pointer now has space for 10 ints
if (container == NULL)
{ //check allocation errors
perror("malloc");
}
for (int i = 0; i < n; i++) //assign values
{
container[i].deg = 0;
}
read_record(&container, n); //pass by reference
//the pointer now has space for 20 ints
}
Alternatively you can return the pointer instead, refering to David Ranieri's answer.
The first function parameter has the pointer to pointer type struct X**. So dereferencing the parameter a you will get a pointer of the type struct X*. Now you may apply the subscript operator that yields lvalue of the type struct X..
That is the function definition will look like
void read_record(struct X** a,int size){
for (int i=0;i<size;i++){
( *a )[i].deg = 0;
}
}
Or this statement
( *a )[i].deg = 0;
may be substituted for this statement
a[0][i].deg = 0;
On the other hand, there is no great sense to declare the first parameter as having the type struct X**. The function can look simpler as for example
void read_record(struct X* a,int size){
for (int i=0;i<size;i++){
a[i].deg = 0;
}
}
and be called like
read_record( container, n );
When you call read_record you pass a pointer to a pointer to the first element of an array of X structures.
But inside the read_record you treat it as a pointer to the first element of an array of pointers to X structures (i.e. as an array of pointers to X). There's a subtle but very important difference here.
If you want to emulate pass-by-reference for the pointer variable, you need to dereference it inside the read_record to get the original pointer (and remember that then you have an array of objects, not pointers):
(*a)[i].deg = 0;
Double pointer is the problem. The code should be:
void read_record(struct X* a,int size){ // Check the change
for (int i=0;i<size;i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container=(struct X*)malloc(sizeof(struct X)*n);
read_record(container,n); // Check the change
}
I don't understand so well how this code works:
#include <stdio.h>
void gswap(void* ptra, void* ptrb, int size)
{
char temp;
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
for (int i = 0 ; i < size ; i++) {
temp = pa[i];
pa[i] = pb[i];
pb[i] = temp;
}
}
int main()
{
int a=1, b=5;
gswap(&a, &b, sizeof(int));
printf("%d , %d", a, b)
}
What I understand is that char has 1 byte(size) in memory and we are using pointers to swap each byte of the int value(4 bytes).
But in the end, how it is possible to dereference a char pointer to int value?
Let's try and figure this out, step by step, with code comments
#include <stdio.h>
//gswap() takes two pointers, prta and ptrb, and the size of the data they point to
void gswap(void* ptra, void* ptrb, int size)
{
// temp will be our temporary variable for exchanging the values
char temp;
// We reinterpret the pointers as char* (byte) pointers
char *pa = (char*)ptra;
char *pb = (char*)ptrb;
// We loop over each byte of the type/structure ptra/b point too, i.e. we loop over size
for (int i = 0 ; i < size ; i++) {
temp = pa[i]; //store a in temp
pa[i] = pb[i]; // replace a with b
pb[i] = temp; // replace b with temp = old(a)
}
}
int main()
{
// Two integers
int a=1, b=5;
// Swap them
gswap(&a, &b, sizeof(int));
// See they've been swapped!
printf("%d , %d", a, b);
}
So, basically, it works by going over any given datatype, reinterpreting as bytes, and swapping the bytes.