• 0

[C] Change values of a struct within a function


Question

Hey guys, the snippet of code below is the definition of a struct called "Game" as well as a function that has been initialised, called "Game throwdice" for my uni project. I have two questions what does the struct function type do? Also I want to be able to update the values in the struct from within the function. I am not allowed to change the definition of the Game throwdice function to use pointers. How would I go about changing the values of the struct? My attempt at making this work is in the second code snippet:


// advance the game to the next turn,
typedef struct _game {
int diceScore;
int currentTurn;
} Game;
// assuming that the dice has just been rolled and produced diceScore
// the game starts in turn -1 (we call this state "Terra Nullis") and
// moves to turn 0 as soon as the first dice is thrown.
Game throwDice (Game g, int diceScore);
[/CODE]

My attempt at implementing this function:

[CODE]
Game throwDice (Game g, int diceScore){
g.diceScore=diceScore; //update the diceScore in the struct
g.currentTurn++; //advance the game to the next turn
return g;
}
[/CODE]

18 answers to this question

Recommended Posts

  • 0
  On 29/04/2012 at 04:14, ~Matt~ said:

what does the struct function type do?

I have absolutely no ideal what you intended with this question, therefore I cannot answer it. I assume that you are familiar with both structures and functions in C, and therefore didn't simply use the wrong terminology. If you would clarify, someone may be able to answer you.

  On 29/04/2012 at 04:14, ~Matt~ said:

How would I go about changing the values of the struct?

This question, on the other hand, is much more straight forward. If you are not allowed to change the function interface, I believe that you already have a workable implementation. Are you having any problems with it?

You can verify that your code works using the driver below.


#include <stdio.h>
#include <time.h>

// advance the game to the next turn,
typedef struct _game {
int diceScore;
int currentTurn;
} Game;

// assuming that the dice has just been rolled and produced diceScore
// the game starts in turn -1 (we call this state "Terra Nullis") and
// moves to turn 0 as soon as the first dice is thrown.
Game throwDice (Game g, int diceScore);

// initialize the structure to start the game
Game startGame (void);

Game throwDice (Game g, int diceScore) {
g.diceScore=diceScore; //update the diceScore in the struct
g.currentTurn++; //advance the game to the next turn
return g;
}

Game startGame (void) {
Game g;
g.diceScore=0;
g.currentTurn=-1;
return g;
}

int main (int argc, char * argv[]) {
Game g=startGame();
printf("Game diceScore = %d\nGame currentTurn = %d\n", g.diceScore, g.currentTurn);
srand(time(NULL));
g=throwDice(g, rand()%6+1);
printf("Game diceScore = %d\nGame currentTurn = %d\n", g.diceScore, g.currentTurn);
return 0;
}
[/CODE]

If you were allowed to modify the function prototype, this would be a much better (and more conventional) way to solve the problem:

[CODE]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// advance the game to the next turn,
typedef struct _game {
int diceScore;
int currentTurn;
} Game;

// assuming that the dice has just been rolled and produced diceScore
// the game starts in turn -1 (we call this state "Terra Nullis") and
// moves to turn 0 as soon as the first dice is thrown.
// returns -1 on failure and 0 on success
int throwDice (Game * g, int diceScore) {
if (!g) return -1;
g->diceScore=diceScore; //update the diceScore in the struct
g->currentTurn++; //advance the game to the next turn
return 0;
}

// Initialize a handle to start the game.
Game * startGame (void) {
Game * g=malloc(sizeof(Game));
g->diceScore=0;
g->currentTurn=-1;
return g;
}

// End the game by destroying its handle.
void endGame (Game * g) {
free( g );
}

int main (int argc, char * argv[]) {
Game * g=startGame();
printf("Game diceScore = %d\nGame currentTurn = %d\n", g->diceScore, g->currentTurn);
srand(time(NULL));
if (throwDice(g, rand()%6+1)<0) {
fprintf(stderr, "The game ended prematurely.\n");
endGame(g);
return -1;
}
printf("Game diceScore = %d\nGame currentTurn = %d\n", g->diceScore, g->currentTurn);
endGame(g);
return 0;
}
[/CODE]

I hope this satisfactorily answers your second question, at least.

  • 0

think of struct as a light weight class and is less expensive.

Unlike classes, structs can be instantiated without using the new. If you do not use new, the fields will remain unassigned and the object cannot be used until all of the fields are initialized. -- I think this was ur problem.

  • 0
  On 29/04/2012 at 05:49, still1 said:

think of struct as a light weight class and is less expensive.

Unlike classes, structs can be instantiated without using the new. If you do not use new, the fields will remain unassigned and the object cannot be used until all of the fields are initialized.

This is C. There are no classes. And even if it wasn't C, I can't think of a language where anything of what you just said would be true. Certainly not C++; in C++ "class" is just an alternate keyword for "struct" and means the exact same thing.
  • 0
  On 29/04/2012 at 04:14, ~Matt~ said:

Hey guys, the snippet of code below is the definition of a struct called "Game" as well as a function that has been initialised, called "Game throwdice" for my uni project. I have two questions what does the struct function type do?

Functions are not "initialized", they are "defined" or "declared". I have no idea what you might mean by "struct function type". The code you posted featured a struct and a function.
  Quote
Also I want to be able to update the values in the struct from within the function. I am not allowed to change the definition of the Game throwdice function to use pointers. How would I go about changing the values of the struct?
You're not allowed to change the definition, but the values of an instance of that type, yes. Think of the type definition as a blueprint for creating instances: it defines what members each instance of "Game" will hold.

It's kind of strange that you ask that question when you do change the values of the struct in the very code you submitted, i.e. in the function throwDice. When you do:

Game g;

g.diceScore = something;

you are changing the value of the member diceScore of the instance "g" of your struct Game. So you seem to already know how to achieve what you want. I'm probably not understanding what your real question is, but it's hard to tell.

  • 0
  On 29/04/2012 at 06:28, Dr_Asik said:

This is C. There are no classes. And even if it wasn't C, I can't think of a language where anything of what you just said would be true. Certainly not C++; in C++ "class" is just an alternate keyword for "struct" and means the exact same thing.

C#

Just trying to help Op and not finding wrong with everything without looking just like what you are doing.

It was my bad thinking that it was c#

  • 0
  On 29/04/2012 at 06:39, Dr_Asik said:

I have no idea what you might mean by "struct function type".

By struct function type, I was just wondering what the difference is/was when declaring a function with

Game throwDice (Game g, int diceScore);[/CODE]

rather than:

[CODE]int throwDice (Game g, int diceScore) ;[/CODE]

It appears that I still do not know what my problem was/is. When I run xorangekiller's implementation of my function it works but when I try write my own the values still don't change:

[CODE]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct _game {
int diceScore;
int currentTurn;
} Game;
Game throwDice(Game g, int diceScore);
Game throwDice(Game g, int diceScore){
g.currentTurn++;
g.diceScore=diceScore;
return g;
}
int main (int argc, const char * argv[])
{
Game g;
srand((unsigned)time(NULL));
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
throwDice(g,rand()%6+1);
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
return 0;
}
[/CODE]

When I run the code I get this as the output:

[CODE]
0 is the turn AND 0 is the diceScore
0 is the turn AND 0 is the diceScore
[/CODE]

  • 0

Why don't you pass the Game object by a pointer and then modify it?

void throwDice(Game * g, int diceScore)
{
		g-&gt;currentTurn++;
		g-&gt;diceScore=diceScore;
}

and then

Game g;
throwDice(&amp;g, rand()%6+1);

Also make sure you perform some initialisation on g before you pass it to throw dice

Edit:

Also the difference between those functions is the return type. One returns an int, the other returns a Game.

  • 0
  On 29/04/2012 at 07:01, ~Matt~ said:

It appears that I still do not know what my problem was/is. When I run xorangekiller's implementation of my function it works but when I try write my own the values still don't change

You're avoiding using pointers by returning the modified Game object. The Game object you have in main() will never be changed by the function. In main, you need to set g equal to the returned value of throwDice(). That's how your copy will be changed. If you don't save the return value of throwDice() - basically, what you have done - then nothing will happen to g.

Basically, your code:


int main (int argc, const char * argv[])
{
Game g;
srand((unsigned)time(NULL));
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
throwDice(g,rand()%6+1);
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
return 0;
}
[/CODE]

Should be changed to:

[CODE]
int main (int argc, const char * argv[])
{
Game g;
srand((unsigned)time(NULL));
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
g = throwDice(g,rand()%6+1);
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
return 0;
}
[/CODE]

  • 0
  On 29/04/2012 at 07:01, ~Matt~ said:

By struct function type, I was just wondering what the difference is/was when declaring a function with

Game throwDice (Game g, int diceScore);[/CODE]

rather than:

[CODE]int throwDice (Game g, int diceScore) ;[/CODE]

1: If you dont know the diferrence there, I think there are bigger issues at hand.

2: If #1, folks, dont bring pointers into this :p

3: This is a uni project and you dont know #1?

I think there is something OP is not telling us, modifiy, etc

  • 0
  Quote
By struct function type, I was just wondering what the difference is/was when declaring a function with

Game throwDice (Game g, int diceScore);[/CODE]

rather than:

[CODE]int throwDice (Game g, int diceScore) ;[/CODE]

The difference is that the first version returns an int, whereas the second version returns a Game. The first term of a function signature is the return type.
  Quote
It appears that I still do not know what my problem was/is. When I run xorangekiller's implementation of my function it works but when I try write my own the values still don't change:

[CODE]#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct _game {
int diceScore;
int currentTurn;
} Game;
Game throwDice(Game g, int diceScore);
Game throwDice(Game g, int diceScore){
g.currentTurn++;
g.diceScore=diceScore;
return g;
}
int main (int argc, const char * argv[])
{
Game g;
srand((unsigned)time(NULL));
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
throwDice(g,rand()%6+1);
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
return 0;
}[/CODE]

That's a very good question and it's fundamental to understand this in C (and any programming language, really). Let's illustrate with a simple example:

[CODE]
void increment(int number) {
number = number + 1;
}

int main() {
int i = 0;
increment(i);
/* what is the value of i? */
}
[/CODE]

The value of i after the call to increment() is still 0, because the parameter "number" [b]is a copy[/b] of the original. Therefore, the copy is incremented, but the original keeps the same value.

So how can we change values using functions in C?? Simple solution: return the new value and assign it to the original variable. Let's illustrate:

[CODE]
int increment(int number) {
number = number + 1;
return number;
}

int main() {
int i = 0;
i = increment(i);
/* what is the value of i? */
}
[/CODE]

What happens here? A copy of i is passed to function increment under the name "number". number is incremented, and its value is returned. This value is then assigned to i, which is now therefore 1.

Notice that here we are copying the parameter into the function and copying it out again on the return. Copying an integer is very cheap, but for larger structures this gets expensive. This is where pointers come in: a pointer allows you to modify the original value without copying it. Example:

[CODE]
void increment(int* number) {
*number = *number + 1;
}

int main() {
int i = 0;
increment(&i);
/* what is the value of i? */
}
[/CODE]

The value of i after the call is 1, because instead of passing a copy of i, we passed a copy of its address in memory, i.e. a pointer. The function increment then accessed the value at that address and modified it (using the "*" notation). Therefore, the original value is modified without having been copied.

That was a basic presentation, you really should read a good tutorial or book on C to gain a solid understanding of these concepts. It's impossible to write any interesting program if you don't understand values vs pointers.

  On 29/04/2012 at 06:59, still1 said:

C#

Just trying to help Op and not finding wrong with everything without looking just like what you are doing.

It was my bad thinking that it was c#

Sorry for sounding harsh, it was 2AM and I couldn't find sleep. I should stop posting at these hours. Anyway, I thought about C# but even then value types are not really "lightweight" classes, and reference types can also be unassigned - their default value is null rather than 0 or some other value. So I figured the comment was inaccurate regardless of language and that apparently irritated me to no end.
  • 0
  On 29/04/2012 at 07:01, ~Matt~ said:

By struct function type, I was just wondering what the difference is/was when declaring a function with

Game throwDice (Game g, int diceScore);[/CODE]

rather than:

[CODE]int throwDice (Game g, int diceScore) ;[/CODE]

It appears that I still do not know what my problem was/is. When I run xorangekiller's implementation of my function it works but when I try write my own the values still don't change:

Based on your last post, I think that your problem is that you are missing some of the subtleties of C. Like rfirth pointed out above, the reason that my implementation works and yours does not entirely comes down to the fact that I was saving the return value and you were not. Notice the difference between the two code snipets below. The former is your implementation and the latter is mine.

[CODE]
throwDice(g,rand()%6+1);
[/CODE]

[CODE]
g = throwDice(g,rand()%6+1);
[/CODE]

However, like I stated in my earlier post, that is not really a good way to do it. What you are actually doing is creating multiple instances of your structure rather than working with just one and reassigning its variables directly (such as my pointer implementation). Therefore, your confusion as to the reason why the function returning the Game type would work but the one returning an int would not is probably due to a misconception on your part about what C is actually doing when you pass an argument to a function. When you pass g to throwDice() as the first argument, a copy of g is created to be used within throwDice(). Hence, when you change g.currentTurn and g.diceScore within the function, only the local copy is changed. The reason that it works when you return your local instance of g is because you are returning another copy of throwDice()'s local instance of g and setting the original instance of g in main() equal to it.

The function would work the way you most likely assume that it should if you passed g to throwDice() by reference. In that case, you would not have a local copy of g, but would, instead, be directly modifying the values within your instance of g in main(). (NOTE: this is only valid in C++, not in C. In C, you need to use pointers (as in my earlier post) to accomplish the same thing.) The driver below demonstrates pass by reference (in C++, there is no such concept in C).

[CODE]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// advance the game to the next turn,
typedef struct _game {
int diceScore;
int currentTurn;
} Game;

// assuming that the dice has just been rolled and produced diceScore
// the game starts in turn -1 (we call this state "Terra Nullis") and
// moves to turn 0 as soon as the first dice is thrown.
// returns -1 on failure and 0 on success
int throwDice (Game &g, int diceScore);

// initialize the structure to start the game
void startGame (Game &g);

int throwDice (Game &g, int diceScore) {
if (diceScore<1 || diceScore>6) return -1;
g.diceScore=diceScore; // update the diceScore in the struct
g.currentTurn++; // advance the game to the next turn
return 0;
}

void startGame (Game &g) {
g.diceScore=0;
g.currentTurn=-1;
}

int main (int argc, char * argv[]) {
Game g;
startGame(g);
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
srand(time (NULL));
if (throwDice(g, rand()%6+1)<0) {
fprintf(stderr, "The game ended prematurely.\n");
return -1;
}
printf("%d is the turn AND %d is the diceScore\n",g.currentTurn, g.diceScore);
return 0;
}
[/CODE]

Edit: Ah! Dr_Asik beat me to it (and has a more thorough explanation). I concede defeat.

  • 0

Thanks for your time guys :)

Appreciated! I understand now. But for this task I am not allowed to change the declaration of the functions, so I cannot use pointers, I have to use the memory expensive way, but I will definitely try write the same function with pointers, for my own benefit!

  • 0
  On 30/04/2012 at 01:13, ~Matt~ said:

Thanks for your time guys :)

Appreciated! I understand now. But for this task I am not allowed to change the declaration of the functions, so I cannot use pointers, I have to use the memory expensive way, but I will definitely try write the same function with pointers, for my own benefit!

You can always declare the structure as a global variable and do it the cheap way memory-wise ;)

  • 0
  On 30/04/2012 at 13:30, gian said:

You can always declare the structure as a global variable and do it the cheap way memory-wise ;)

"Beware of the dark side. Globals, gotos; the dark side of the Force are they. Easily they flow, quick to join you in a fight. If once you start down the dark path, forever will it dominate your destiny, consume you it will.."

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Cloud storage of course is not for all types of files users have but more users should be taking advantage of the cloud because otherwise their files are not backed up at all. Most regular users do not do that so automatic backup of their data is a good idea. The cloud is just another service/tool.
    • People do this with their iPhones and Androids. Smart people use cloud services as backups. No company deletes your account just like that. No company blocks your data for no reason. Having an external SSD and a paid cloud service is a must for anyone who works and for anyone who has sensitive data that needs to be backed up several times. Every CEO of a company has a corporate cloud service on their devices, but home users shouldn't use it, why?
    • Camtasia screen recorder now has a free version that works in your browser by Aditya Tiwari TechSmith, the minds behind Camtasia, has announced an online version of its popular screen recording and video editing tool. The web-based version, called Camtasia Online, is now available through popular web browsers like Google Chrome and Safari. Camtasia Online is essentially a stripped-down version of its desktop counterpart. It is designed to let you screen record, customize, share, and collaborate on high-quality videos without needing to download any software or purchase a subscription. Screen recording tools are often used to create step-by-step walkthroughs and tutorials, personalized feedback or coaching, and showcase a product or service. Camtasia has been around since 2002 and is primarily accessible through paid offerings. The screen recorder has over 34 million users globally. TechSmith offers a free trial of the desktop version, but the exported files automatically include a watermark. That's not the case with its modern counterpart, according to the company, which doesn't require any subscription. Note that while the online screen recorder is free to use, you still need a TechSmith account to use it. "While this first release focuses on streamlined creation, it will continue to grow in capability, and users can move projects into the Camtasia desktop editor for more advanced editing when needed,” TechSmith's CTO, Tony Lambert, said in an emailed statement. The web-based version allows you to create 1080p short clips (Scenes) of up to 5 minutes in length, with options to record a specific app, window, or the entire screen. It can record the screen, camera, and microphone on separate layers for more flexibility during editing. You can record multiple scenes and export them as a single video file. Camtasia Online offers a variety of visual effects and backgrounds, and the ability to pick a custom size and position on the screen. For instance, you can place the screen recording in the top-left or bottom-right corner of the screen, depending on your preference. Camtasia Online comes with more than 85 pre-defined "looks" to match your preference, its maker said. You can remove the background, add borders, drop shadows, make corners round, add reflections, and more, before and after recording a scene. You can also trim a video after recording with support for reversible changes. The online screen recorder also lets you collaborate with other users by sending invitation links. You can either give them access to the entire project or just a single scene. You can also preview the scenes before exporting them or re-record if something doesn't feel right. TechSmith also offers integration with Camtasia 2025's desktop version, allowing you to utilize additional features such as transitions, annotations, and dynamic captions. You can click on the Export button to download the project and use it in the desktop editor. Overall, Camtasia Online could be a suitable option for quick screen recording sessions and a viable choice for beginners. However, one downside is that it can be a bit tricky to download the video file directly through your browser. First, click on the "Export to Screencast" option in Export settings, which opens TechSmith's online hosting service. Then, make sure you're signed in to your TechSmith account, and click on More > Download to download the video file to your device.
    • Intel is pretty consistent about dropping a new CPU every year, typically in Q3. The fact that we are starting to get more information now implies they are on track.
    • TerraMaster D4 SSD review: Palm-sized DAS with up to 32TB of storage over USB4 by Steven Parker TerraMaster is back with another disk enclosure. I was offered the chance to take a look at their new D4 SSD, which is a palm-sized DAS that supports four M.2 SSDs ahead of its launch, today, on June 17. This follows our review of the all SATA D9-320 that we did last month, and the D5 Hybrid and D8 Hybrid, both of which are essentially multi-disk (HDD and SSD) enclosures for external backup, or to expand the capacity of a NAS. Here are the full specs of it: TerraMaster D4 SSD Dimensions: 138 x 60 x 140 mm Weight: 419g (with 3x M.2 SSDs) Power: 24W (100V to 240V AC) 50/60 HZ, Single Frequency System Fan: 50 x 50 x 10mm x3 Max Noise Level: 19 dB(A) using M.2 SSDs in standby mode; Test environment noise: 17.3dB(A); Test distance: 1m Compatible Disk Types: PCIe NVMe M.2 2280 SSD Reading Speed (max.) Writing Speed (max.) 3257 MB/s (Samsung 990 Pro 4TB x4 RAID0; 1600MB/s 4TB x1 3192 MB/s (Samsung 990 Pro 4TB x4 RAID0; 1500MB/s 4TB x1 Power Consumption: 15.0 W (Fully loaded Seagate 2TB M.2 SSDs in read/write state) 6.0 W (Fully loaded Seagate 2TB M.2 SSDs in hibernation) Raw Capacity: 32TB (8TB SSD x4) RAIDs Supported: SINGLE DISK Power saving: Hibernation Ports: USB4 40Gbps DC IN 12V Barrelport (MSRP) Price: $299.99 First, I should mention that TerraMaster only put SINGLE DISK support in the RAID specification, however unlike the D9-320 9-bay HDD enclosure, I was surprised to see that it actually supports both Striped and Spanned volumes in Windows 11, so you can get RAID1 in Windows 11 with this if you wanted, or simply combine all of the available drives into a single volume spanning the size of all drives combined. Technically, they are correct with the only SINGLE disk support, that is, if you plan to connect it to a NAS. Because it connects over USB, this means you will only be able to create usbshares, not storage pools. However, it is a nice surprise that Windows supports more functions with this D4 SSD than a NAS offers, which may also result in how you decide to use it. Also, for some reason, they have put that it weighs 600 grams. I think this is the package weight, because I weighed the D4 SSD after putting in three SSDs, and it came to 419 grams, which is really light! What's in the box D4 SSD device USB Type-C cable (C to C) 0.8m Power adapter Quick installation guide Limited warranty notice Bag of 2x M.2 screws I should mention that the "Quick Installation Guide" is simply a card with a QR code that links to https://start.terra-master.com. It requests your email and product details, which then opens to a full online User Guide. After getting to the end of the online User Guide (37 pages), which frustratingly encountered really slow page loads at times, there's a link to download a PDF of the User Manual. Design The design of the D4 SSD matches that of the F8 SSD Plus that I reviewed last year; in fact, it shares almost the same dimensions, but is 3.7cm shorter than its full NAS SSD counterpart, which is another example of how TerraMaster disk enclosures closely match their NAS sibling. It is essentially a metal frame with what I would call a matte black plastic cover. It is a bit of a dust and fingerprint magnet, too, but a quick wipe, and it's all gone, unlike what you would see with a glossy plastic exterior. It has a slightly textured feel to it and definitely feels premium, but also not in such a way that it would easily slip out of your hand. On the front, the D4 SSD is completely bare aside from a small sticker with D4 SSD printed on it; both sides are the same, with the TERRAMASTER logo stamped in the center. Unlike the D5-, D8 Hybrid, and NAS' in the same class (2- and 4-bay,) the logos do not double as ventilation on the D4 SSD. Around the back is a pretty bare affair with regulatory information stamped on it, then you have the Type C USB4 port and barrel power port input along with the screw that once removed, lets you slide off the cover to access the internals and manage the M.2 SSDs. Top Bottom The top uses the full surface area aside from the power button to assist with ventilation, and on the bottom, there are two 50 x 50 x 10mm intake fans that are very quiet. Installation Well, like the D9-320, there's hardly anything to it. Take off the screw around the back and screw in your PCIe NVMe M.2 2280 SSDs. They run at a (combined) max speed of USB4 (40 Gbps). TerraMaster includes a screw on each M2 connector, so need to go hunting, there are also two "backup screws" included in the box. For our review, we used two MP44Q 4TB NVMe SSDs ($224.99 on Amazon or Newegg) that TEAMGROUP supplied us with, and a 2TB Rocket 4 Plus ($219.99 on Newegg) that Sabrent sent to us. They are all PCIe 4.0 x4 drives. TerraMaster also uploaded a video to YouTube that shows how to install the storage options. Usage First, a bit of background on the capabilities of the D4 SSD. The ASMedia ASM2464PDX chip offers four lanes at PCIe 4.0 x 1; however, you can only expect to see up to 3257 MB/s speeds, and that will need to be in a RAID configuration; it basically translates to speeds you would expect from a traditional PCIe 3.0 SSD. This drops to around half that speed if the disks are being used independently in SINGLE disk mode. Here is how TerraMaster breaks it down: Unlike the D9-320 that we recently tested, it is not possible to daisy chain the D4 SSD with multiple units. As of writing, TerraMaster is not offering it in any other sizes (so, there is no D8 SSD option). RAID Happily, you can create a Striped or Spanned Volume of the disks in Windows, but be aware that it will only combine the total size of the smallest-sized SSD (so if you have 2TB + 4TB + 4TB, a volume of 3x 2TB will be created). In TOS 6 the same is true with the default TRAID setting, which is basically TerraMaster's own flavor of RAID5. Creating a storage pool on the D4 SSD in TOS 6 Creating a 3.71TB Storage pool (using two 4TB SSDs in TRAID) took around three hours to synchronize. On the official website, it is suggested that you download TPC Backupper, which is not included in the box, on a USB or onboard storage in the D8 Hybrid. There's a card that also instructs to download TPC Backupper. Still, I find that a bit of a shame because even most Razer or Logitech keyboards and mice include the setup program for Synapse or Logitech Options when you connect these devices to your Windows PC. Upon installing TPC Backupper by AOMEI a web page automatically opens in the default browser, thanking for a successful installation of what is actually a rebranded version of the free AOMEI Backupper Standard, and it "helpfully" suggests upgrading to a paid version for more features. The nag to upgrade to a paid version of the software seems a bit desperate if you ask me. I decided to emulate a daily backup that I usually do with the excellent SyncFolder, which basically backs up my Documents and Pictures folders from my main PC to my NAS Cloud drive. For this, I used the TPC Backupper app that I mentioned earlier. D4 SSD attached to local PC, local disk backup to D4 SSD over USB The process took a little under ten minutes to back up 34,979 files in 2,213 folders totaling 35,7GB into an .afi image file on a Striped volume. Restoring to the same local SSD only took 2m30s, which is impressive. D9-320 attached to local PC, backup to NAS over network Next, I backed up the same Documents and Pictures folders from the Striped volume in the D4 SSD to my Cloud backup over the network, and this took 11m20s. Restoring to the D4 SSD took just under three minutes, which is only half a minute longer than restoring the same data locally. Local PC backup over LAN to D4 SSD attached to NAS over USB Lastly, I ran the backup with the D4 SSD attached directly to my TerraMaster F4-424 Max over USB, so this meant copying the Documents and Pictures folder from my local PC over my LAN to the D4 SSD. The process took 14m33s to back up 34,979 files in 2,213 folders totaling 35,7GB into an .afi image file on the Simple volume, which is a little longer over the network than with the D4 SSD attached via USB to my local PC. Restoring the data locally over the network only took 1m30s, which was a minute quicker than restoring from the D4 SSD when attached locally, for some reason. Drive speed Striped volume Simple volume However, back to the drive setup, I ran CrystalDiskMark 8.0.5 in Windows 11 24H2 with the D4 SSD attached to that PC. I included both RAID and SINGLE disk mode, and the results definitely align with TerraMaster's drive speed claims, mentioned earlier in this review. I tried to measure the noise, but it did not register over the (roughly) 50dB of ambient noise of my work-from-home office. We will have to take TerraMaster's word for the claim about noise levels being as low as 19 dB. The Cooler Master NR200P Max towers above the TerraMaster D4 SSD Conclusion TerraMaster markets the D4 SSD as "specifically designed for media creation and video production applications," but also says that it "serves as an ideal external storage expansion solution for Mac mini and can be used as a Mac OS boot drive." Sorry, but I do not have a Mac mini to test this claim. TerraMaster also claims that this would suit gamers, for its "seamless experience indistinguishable from running on a local drive, with truly zero-latency performance." So it really has several use case applications depending on your wishes, and affordability to populate with up to four (large) SSDs. It looks premium, but it is what it is, essentially a plastic shell of a DAS. But it does not feel cheap either, the bottom intake fans are quiet, and overall, it is a nice-looking device that will not take up much room anywhere you place it. The added bonus here is RAID support, unlike with the D9-320 in Windows. However, do not expect RAID support on any NAS other than TerraMaster's own TOS 6 because you cannot create a storage pool over USB (at least in Synology DSM). Say you had a few one- or two-terabyte SSDs lying around, you could stick them all in and create a striped volume for anything up to 8TB for a really large storage volume in Windows. If I had any complaints at all, it would be how it does not really fully support 3rd party NAS' for creating a storage pool, but that would probably require an eSATA port. Secondly, I would have preferred to have seen a toolless method for installing and managing the SSDs. Most modern motherboards now use the toolless method of a clip or latch for M.2 SSDs, and given that the D4 SSD only supports 2280-sized SSDs, I don't feel this is a huge ask. You can purchase the TerraMaster D4 SSD for $299.99 from today (June 17) on the official website. As an Amazon Associate, we earn from qualifying purchases.
  • Recent Achievements

    • Experienced
      dismuter went up a rank
      Experienced
    • One Month Later
      mevinyavin earned a badge
      One Month Later
    • Week One Done
      rozermack875 earned a badge
      Week One Done
    • Week One Done
      oneworldtechnologies earned a badge
      Week One Done
    • Veteran
      matthiew went up a rank
      Veteran
  • Popular Contributors

    1. 1
      +primortal
      693
    2. 2
      ATLien_0
      269
    3. 3
      Michael Scrip
      209
    4. 4
      +FloatingFatMan
      186
    5. 5
      Steven P.
      142
  • Tell a friend

    Love Neowin? Tell a friend!